package lib import "fmt" func Run() { fmt.Println("something very NB") }但是现实是,这个调用方不是同一个项目的,代码不在一起,是其它项目需要用,咋办呢?有人说,把代码copy给别人,比较low,而且有时候代码要保密。有人说,使用http服务,写个接口出来,扔一个API文档,这个方案完全可以,但是不是今天的主角。或许,我们也可以使用rpc通信。
4.函数还要有一个返回值 error
package golang_rpc import "log" type Add struct { } func (a *Add) Plus(request Request, response *Response) error { // 堆代码 duidaima.com response.Result = request.A + request.B log.Printf("Add...%d + %d", request.A, request.B) return nil } type Request struct { A int B int } type Response struct { Result int }Server端
package main import ( . "gRPC/golang-rpc" "log" "net/http" "net/rpc" ) func main() { add := new(Add) _ = rpc.Register(add) rpc.HandleHTTP() log.Println("rpc server started at port 8888") if err := http.ListenAndServe(":8888", nil); err != nil { panic(err) } }Client端
package main import ( . "gRPC/golang-rpc" "log" "net/rpc" ) func main() { dial, err := rpc.DialHTTP("tcp", ":8888") if err != nil { panic(err) } args := Request{ A: 1, B: 2, } var response = Response{} err = dial.Call("Add.Plus", args, &response) if err != nil { panic(err) } log.Printf("a = %d, b= %d, result = %d", args.A, args.B, response.Result) }这只是展示了Go rpc的一种用法,Go rpc的除了支持tcp之外,还可以使用json,也就是jsonrpc,其编码方式是使用json而不是默认的Gob。
├── client │ └── client.go ├── go.mod ├── go.sum ├── proto │ ├── hello.pb.go │ └── hello.proto └── server.go切换到终端,在proto目录下执行protoc --go_out=plugins=grpc:. *.proto命令生成一个pb.go文件,这是一个go语法的文件,里面的东西非常多,我们真正用到的就是这个。
package main import ( "context" "fmt" pb "gRPC/proto" "google.golang.org/grpc" "log" "net" ) type HelloService struct{} func (s *HelloService) Hello(ctx context.Context, r *pb.HelloRequest) (*pb.HelloResponse, error) { fmt.Println("new request...") return &pb.HelloResponse{Response: r.GetRequest() + " Server"}, nil } const PORT = "8080" func main() { server := grpc.NewServer() pb.RegisterHelloServiceServer(server, &HelloService{}) listen, err := net.Listen("tcp", ":"+PORT) if err != nil { log.Fatalf("net.Listen err: %v", err) } _ = server.Serve(listen) }server端的主要作用是实现服务定义的接口,然后把服务注册到rpc server里面,最后启动服务等待请求的到来,和http服务有点类似。虽然服务启动了,但是这时候无法像像http一样使用浏览器或者其它工具去访问,我们必须使用特定的客户端来访问服务,下面是客户端的代码:
package main import ( "context" pb "gRPC/proto" "google.golang.org/grpc" "log" ) const PORT = "8080" func main() { conn, err := grpc.Dial(":"+PORT, grpc.WithInsecure()) if err != nil { log.Fatalf("grpc.Dial err: %v", err) } defer conn.Close() client := pb.NewHelloServiceClient(conn) resp, err := client.Hello(context.Background(), &pb.HelloRequest{ Request: "Hello gRPC", }) if err != nil { log.Fatalf("client.Search err: %v", err) } log.Printf("resp: %s", resp.GetResponse()) }最后,先启动server,然后运行client。