1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/andot-hprose-go

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

Hprose

Hprose 2.0 для Go

Присоединяйтесь к чату на https://gitter.im/hprose/hprose-golang Статус сборки GoDoc Go Report Card codebeat badge Coverage Status License

Hprose 2.0 для Go китайская документация>---

Hprose — это высокопроизводительный движок удаленного объектного сервиса.

Это современный, легковесный, многопрограммный, многоплатформенный, объектно-ориентированный, высокопроизводительный, динамический удаленный коммуникационный middleware. Он не только прост в использовании, но и мощен. Вам потребуется немного времени для изучения, после чего вы сможете использовать его для создания многопрограммных и многоплатформенных распределенных приложений.

Hprose поддерживает множество языков программирования, например:

  • AAuto Quicker
  • ActionScript
  • ASP
  • C++
  • Dart
  • Delphi/Free Pascal
  • dotNET (C#, Visual Basic...)
  • Golang
  • Java
  • JavaScript
  • Node.js
  • Objective-C
  • Perl
  • PHP
  • Python
  • Ruby
  • ...

С помощью Hprose вы можете легко и эффективно взаимодействовать между этими языками программирования.

Этот проект представляет собой реализацию Hprose 2.0 для Golang.

Установка

go get -u -v github.com/hprose/hprose-golang

Использование

HTTP-сервер

На основе net/http

package main

import (
	"net/http"

	"github.com/hprose/hprose-golang/rpc"
)

func hello(name string) string {
	return "Hello " + name + "!"
}

func main() {
	service := rpc.NewHTTPService()
	service.AddFunction("hello", hello)
	http.ListenAndServe(":8080", service)
}

На основе fasthttp

package main

import (
	rpc "github.com/hprose/hprose-golang/rpc/fasthttp"
	"github.com/valyala/fasthttp"
)

func hello(name string) string {
	return "Hello " + name + "!"
}

func main() {
	service := rpc.NewFastHTTPService()
	service.AddFunction("hello", hello)
	fasthttp.ListenAndServe(":8080", service.ServeFastHTTP)
}
```#### Основанный на Gin

```go
package main

import (
	"github.com/hprose/hprose-golang/rpc"
	"gopkg.in/gin-gonic/gin.v1"
)

func hello(name string) string {
	return "Hello " + name + "!"
}

func main() {
	service := rpc.NewHTTPService()
	service.AddFunction("hello", hello)
	router := gin.Default()
	router.Any("/path", func(c *gin.Context) {
		service.ServeHTTP(c.Writer, c.Request)
	})
	router.Run(":8080")
}

Основанный на Echo

package main

import (
	"github.com/hprose/hprose-golang/rpc"
	"github.com/labstack/echo"
)

func hello(name string) string {
	return "Hello " + name + "!"
}

func main() {
	service := rpc.NewHTTPService()
	service.AddFunction("hello", hello)
	e := echo.New()
	e.Any("/path", echo.WrapHandler(service))
	e.Start(":8080")
}

Основанный на Beego

package main

import (
	"github.com/astaxie/beego"
	"github.com/hprose/hprose-golang/rpc"
)

func hello(name string) string {
	return "Hello " + name + "!"
}

func main() {
	service := rpc.NewHTTPService()
	service.AddFunction("hello", hello)
	beego.Handler("/path", service)
	beego.Run()
}

Основанный на Iris

package main

import (
	rpc "github.com/hprose/hprose-golang/rpc/fasthttp"
	"github.com/kataras/iris"
)

func hello(name string) string {
	return "Hello " + name + "!"
}

func main() {
	service := rpc.NewFastHTTPService()
	service.AddFunction("hello", hello)
	iris.Any("/path", func(c *iris.Context) {
		service.ServeFastHTTP(c.RequestCtx)
	})
	iris.Listen(":8080")
}

HTTP-клиент

Синхронное вызов

package main

import (
	"fmt"

	"github.com/hprose/hprose-golang/rpc"
)

type HelloService struct {
    Hello func(string) (string, error)
    Hello2 func(string) string `name:"hello"`
}

func main() {
	client := rpc.NewHTTPClient("http://127.0.0.1:8080/")
	var helloService *HelloService
	client.UseService(&helloService)
	fmt.Println(helloService.Hello("мир"))
	fmt.Println(helloService.Hello2("мир"))
}
```Go не поддерживает перегрузку функций/методов, но некоторые другие языки поддерживают. Поэтому Hprose предоставляет "Алгоритм переименования функций/методов" для вызова перегруженных методов на других языках. Вы можете использовать его для вызова одной и той же функции/метода с разными именами.Для этого вам нужно определить несколько полей функций, соответствующих одному и тому же удаленному методу, с помощью одного и того же тега `name`.

Если серверная функция/метод возвращает ошибку (должна быть последним параметром) или вызывает панику, клиент получит её. Если клиентское поле функции определяет выходной параметр ошибки (должен быть последним), вы можете получить серверную ошибку или панику из него. Если клиентское поле функции не определяет выходной параметр ошибки, вызов клиента вызовет панику при получении серверной ошибки или паники.

#### Асинхронное вызов

```go
package main

import (
	"fmt"
	"time"

	"github.com/hprose/hprose-golang/rpc"
)

type HelloService struct {
	Hello func(func(string, error), string)
	Hello2 func(func(string), string) `name:"hello"`
}
func main() {
	client := rpc.NewHTTPClient("http://127.0.0.1:8080/")
	var helloService *HelloService
	client.UseService(&helloService)
	helloService.Hello(func(result string, err error) {
		fmt.Println(result, err)
	}, "async world")
	helloService.Hello2(func(result string) {
		fmt.Println(result)
	}, "async world")
	time.Sleep(time.Second)
}

Если первый входной параметр является обратным вызовом функции, вы можете вызывать удалённый метод асинхронно.

Входной параметр обратного вызова определяется подобно выходным параметрам в синхронном вызове метода. Однако, если вы опустите последний параметр ошибки, асинхронный вызов НЕ вызовет паники, ошибка будет проигнорирована.

Передача параметров по ссылкеHprose поддерживает передачу параметров по ссылке. Параметры должны быть указателями и иметь поле func с тегом byref:"true". Например:

package main

import (
	"fmt"

	"github.com/hprose/hprose-golang/rpc"
)

func swap(a, b *int) {
	*b, *a = *a, *b
}

type SwapService struct {
	Swap func(a, b *int) error `byref:"true"`
}

func main() {
	server := rpc.NewTCPServer("")
	server.AddFunction("swap", swap)
	server.Handle()
	client := rpc.NewClient(server.URI())
	var swapService *SwapService
	client.UseService(&swapService)
	a := 1
	b := 2
	swapService.Swap(&a, &b)
	fmt.Println(a, b)
	client.Close()
	server.Close()
}

Вы обнаружите, что Hprose также поддерживает TCP-сервер и TCP-клиент в этом примере.

Пользовательские структуры

Вы можете передавать объекты пользовательских структур напрямую между клиентом Hprose и сервером Hprose. Использование метода Register для регистрации вашей пользовательской структуры — это единственное, что вам нужно сделать.

Например:

package main

import (
    "fmt"
    "github.com/hprose/hprose-golang/io"
    "github.com/hprose/hprose-golang/rpc"
)

type TestUser struct {
    Name     string
    Sex      int
    Birthday time.Time
    Age      int
    Married  bool
}

type RemoteObject struct {
    GetUserList func() []TestUser
}

func main() {
    io.Register(TestUser{}, "User")
    client := rpc.NewClient("http://www.hprose.com/example/")
    var ro *RemoteObject
    client.UseService(&ro)
    fmt.Println(ro.GetUserList())
}

Первый аргумент метода Register — это объект или указатель на вашу пользовательскую структуру. Второй аргумент — это псевдоним вашей пользовательской структуры.

Имя вашей пользовательской структуры может быть разным на клиенте и сервере, если они зарегистрировали одинаковый псевдоним.Сервер этого примера написан на PHP. На самом деле, вы можете использовать пользовательские структуры с сервером на Go тоже.

Псевдонимы полей пользовательских структур

Первая буква имени поля будет автоматически приведена к нижнему регистру при сериализации Hprose. Поэтому нам не нужно определять тег для реализации этой функции, как при сериализации JSON, когда мы взаимодействуем с другими языками. Но это не означает, что Hprose не может поддерживать определение псевдонимов полей с помощью тегов. На самом деле, это не единственный его функционал, и он может быть совместим с определением псевдонимов полей в JSON-способе сериализации. Например:

type User struct {
	Name                         string `json:"n"`
	Age                          int    `json:"a"`
	ThisFieldWillNotBeSerialized string `json:"-"`
}

io.Register(User{}, "User", "json")

Вышеуказанный структурированный тип определен для JSON-сериализации. Однако, когда мы вызываем Register, передавая третьим аргументом "json", мы можем использовать псевдонимы полей, определенные в тегах json для сериализации Hprose. Если псевдоним поля равен "-", поле не будет сериализовано.

Вы можете изменить тег json на что-то другое в определении структуры, например, на hprose, при условии, что это будет соответствовать значению третьего аргумента в Register.

Hprose ProxyHprose поддерживает публикацию специального метода: MissingMethod. Все методы, которые не были явно опубликованы, будут перенаправлены к этому методу. Вы можете использовать его для реализации hprose-прокси. И Hprose предоставляет опцию ResultMode для улучшения производительности прокси-сервера. Вы можете использовать её следующим образом:```go

package main

import ( "net/http" "reflect"

"github.com/hprose/hprose-golang/rpc"

)

type HproseProxy struct { client rpc.Client settings rpc.InvokeSettings }

func newHproseProxy() *HproseProxy { proxy := new(HproseProxy) proxy.client = rpc.NewClient("http://www.hprose.com/example/") proxy.settings = rpc.InvokeSettings{ Mode: rpc.Raw, ResultTypes: []reflect.Type{reflect.TypeOf(([]byte)(nil))}, } return proxy }

func (proxy *HproseProxy) Proxy( name string, args []reflect.Value, context rpc.Context) ([]reflect.Value, error) { return proxy.client.Invoke(name, args, &proxy.settings) }

func main() { service := rpc.NewHTTPService() service.AddMissingMethod(newHproseProxy().Proxy, rpc.Options{Mode: rpc.Raw}) http.ListenAndServe(":8080", service) }


Вы также можете определить поле-функцию с тегом `mode` в клиенте, и возвращаемое значение должно быть `[]byte`. Опция `ResultMode` сервера устанавливается параметром `Options`.

Опция `ResultMode` имеет 4 значения:

* `Normal`
* `Serialized`
* `Raw`
* `RawWithEndTag`

Значение `Normal` является значением по умолчанию.

В режиме `Serialized` возвращаемое значение представляет собой сериализованные данные hprose в `[]byte`, но аргументы и исключения будут распарсены в обычное значение. В режиме `Raw` результат будет возвращен напрямую в формате `[]byte`, но данные результата не содержат тег `TagEnd` библиотеки hprose.

Режим `RawWithEndTag` похож на режим `Raw`, но содержит тег `TagEnd` библиотеки hprose.

С помощью опции `ResultMode` вы можете хранить, кэшировать и пересылать результат в исходном формате.

### Простой режим

По умолчанию данные между клиентом и сервером hprose могут содержать внутренние ссылки. Если ваши данные не содержат внутренних ссылок, вы можете включить простой режим для улучшения производительности.```go
package main

import (
	"fmt"

	"github.com/hprose/hprose-golang/rpc"
)

func hello(name string) string {
	return "Hello " + name + "!"
}

type HelloService struct {
	Hello func(string) (string, error) `simple:"true"`
}

func main() {
	server := rpc.NewTCPServer("")
	server.AddFunction("hello", hello, rpc.Options{Simple: true})
	server.Handle()
	client := rpc.NewClient(server.URI())
	var helloService *HelloService
	client.UseService(&helloService)
	fmt.Println(helloService.Hello("World"))
	client.Close()
	server.Close()
}

WebSocket сервер и клиент

WebSocket сервер

package main

import (
	"net/http"
	"runtime"

	rpc "github.com/hprose/hprose-golang/rpc/websocket"
)

func hello(name string) string {
	return "Hello " + name + "!"
}

func main() {
	service := rpc.NewWebSocketService()
	service.AddFunction("hello", hello)
	http.ListenAndServe(":8080", service)
}

WebSocket клиент

package main

import (
	"fmt"

	rpc "github.com/hprose/hprose-golang/rpc/websocket"
)

type HelloService struct {
	Hello func(string) (string, error)
}

func main() {
	client := rpc.NewWebSocketClient("ws://127.0.0.1:8080/")
	var helloService *HelloService
	client.UseService(&helloService)
	fmt.Println(helloService.Hello("world"))
}

Unix Socket сервер и клиент

Unix Socket сервер

package main

import (
	"net/http"
	"runtime"

	"github.com/hprose/hprose-golang/rpc"
)

func hello(name string) string {
	return "Hello " + name + "!"
}

func main() {
	server := rpc.NewUnixServer("unix:///tmp/hprose.sock")
	server.AddFunction("hello", hello)
	server.Start()
}

Unix Socket клиент

package main

import (
	"fmt"

	"github.com/hprose/hprose-golang/rpc"
)

type HelloService struct {
	Hello func(string) (string, error)
}

func main() {
	client := rpc.NewUnixClient("unix:///tmp/hprose.sock")
	var helloService *HelloService
	client.UseService(&helloService)
	fmt.Println(helloService.Hello("мир"))
}

Бенчмарк

Hprose быстрее, чем Go RPC. Вы можете запустить бенчмарк следующим образом:

go test --bench=".*" github.com/hprose/hprose-golang/examples/bench
```* go1.7.1 darwin/amd64
* macOS Sierra
* iMac (Retina 5K, 27-дюймовый, конец 2015 года)
* Процессор 4 ГГц Intel Core i7
* Память 32 ГБ 1867 МГц DDR3

BenchmarkParallelHprose2-8 200000 11230 ns/op BenchmarkParallelHprose2Unix-8 300000 5234 ns/op BenchmarkParallelGobRPC-8 100000 16675 ns/op BenchmarkParallelGobRPCUnix-8 200000 6798 ns/op BenchmarkParallelJSONRPC-8 100000 17261 ns/op BenchmarkParallelJSONRPCUnix-8 200000 7917 ns/op

BenchmarkHprose2-8 50000 34287 ns/op BenchmarkHprose2Unix-8 200000 11470 ns/op BenchmarkGobRPC-8 30000 45576 ns/op BenchmarkGobRPCUnix-8 100000 24216 ns/op BenchmarkJSONRPC-8 30000 51298 ns/op BenchmarkJSONRPCUnix-8 50000 27408 ns/op


Комментарии ( 0 )

Вы можете оставить комментарий после Вход в систему

Введение

Hprose — это высокопроизводительный движок для удалённого обслуживания объектов. Это новый тип облегчённого, кроссплатформенного и объектно-ориентированного высокопроизводительного промежуточного программного обеспечения для динамической удалённой связи. Он не только лёгок в изучении и использовании, но и обладает мощными функциями. Данный проек... Развернуть Свернуть
Go и 2 других языков
Отмена

Обновления

Пока нет обновлений

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/andot-hprose-go.git
git@api.gitlife.ru:oschina-mirror/andot-hprose-go.git
oschina-mirror
andot-hprose-go
andot-hprose-go
master