Hprose 2.0 для Go китайская документация>---
Hprose — это высокопроизводительный движок удаленного объектного сервиса.
Это современный, легковесный, многопрограммный, многоплатформенный, объектно-ориентированный, высокопроизводительный, динамический удаленный коммуникационный middleware. Он не только прост в использовании, но и мощен. Вам потребуется немного времени для изучения, после чего вы сможете использовать его для создания многопрограммных и многоплатформенных распределенных приложений.
Hprose поддерживает множество языков программирования, например:
С помощью Hprose вы можете легко и эффективно взаимодействовать между этими языками программирования.
Этот проект представляет собой реализацию Hprose 2.0 для Golang.
go get -u -v github.com/hprose/hprose-golang
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)
}
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")
}
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")
}
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()
}
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")
}
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)
}
Если первый входной параметр является обратным вызовом функции, вы можете вызывать удалённый метод асинхронно.
Входной параметр обратного вызова определяется подобно выходным параметрам в синхронном вызове метода. Однако, если вы опустите последний параметр ошибки, асинхронный вызов НЕ вызовет паники, ошибка будет проигнорирована.
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
.
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()
}
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)
}
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"))
}
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()
}
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 )