参考链接1 对grpc有非常详细的教程,这里主要讲一些文章中没讲过的。 我们主要基于文章最后提供的链接分析一下其中的代码。
我们来看看.pb.go和_grpc.pb.go文件。目前这是我们的pb文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 syntax = "proto3" ; option go_package = "hello_server/pb" ;package pb; service Greeter { rpc SayHello (HelloRequest) returns (HelloReply) {} rpc LotsOfReplies(HelloRequest) returns (stream HelloReply); rpc LotsOfGreetings(stream HelloRequest) returns (HelloReply); rpc BidiHello(stream HelloRequest) returns (stream HelloReply); } message HelloRequest { string name = 1 ; } message HelloReply { string message = 1 ; }
GO
pb.go这个文件主要包含的是一些proto文件定义的类型和他的序列化方法。
1 2 3 4 5 6 7 8 type HelloRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` }
GO
Name 后双引号内容的含义:
bytes 指定字段的编码类型, 还可以是int32, int64, float,double, bool….
1表示的字段的编号
name表示的字段名称
opt表示是可选的,还有req(require),rep(repeated)
1 2 3 4 5 6 func (x *HelloRequest) GetName() string { if x != nil { return x.Name } return "" }
GO
这里是Get我们自定义字段的方法。这个文件内其他的方法主要是序列化,反序列化,配合prorobuf使用。目前可以暂时不太关注。
_ grpc.pb.go server1 2 3 4 5 6 7 8 9 10 11 12 13 14 type GreeterServer interface { SayHello(context.Context, *HelloRequest) (*HelloReply, error ) LotsOfReplies(*HelloRequest, Greeter_LotsOfRepliesServer) error LotsOfGreetings(Greeter_LotsOfGreetingsServer) error BidiHello(Greeter_BidiHelloServer) error mustEmbedUnimplementedGreeterServer() }
GO
这是你需要实现的接口,然后流式API会新加入一些东西。
1 2 3 4 5 6 7 8 9 10 11 12 13 type Greeter_LotsOfRepliesServer interface { Send(*HelloReply) error grpc.ServerStream }type greeterLotsOfRepliesServer struct { grpc.ServerStream }func (x *greeterLotsOfRepliesServer) Send(m *HelloReply) error { return x.ServerStream.SendMsg(m) }
GO
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 type Greeter_LotsOfGreetingsServer interface { SendAndClose(*HelloReply) error Recv() (*HelloRequest, error ) grpc.ServerStream }type greeterLotsOfGreetingsServer struct { grpc.ServerStream }func (x *greeterLotsOfGreetingsServer) SendAndClose(m *HelloReply) error { return x.ServerStream.SendMsg(m) }func (x *greeterLotsOfGreetingsServer) Recv() (*HelloRequest, error ) { m := new (HelloRequest) if err := x.ServerStream.RecvMsg(m); err != nil { return nil , err } return m, nil }
GO
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 type Greeter_BidiHelloServer interface { Send(*HelloReply) error Recv() (*HelloRequest, error ) grpc.ServerStream }type greeterBidiHelloServer struct { grpc.ServerStream }func (x *greeterBidiHelloServer) Send(m *HelloReply) error { return x.ServerStream.SendMsg(m) }func (x *greeterBidiHelloServer) Recv() (*HelloRequest, error ) { m := new (HelloRequest) if err := x.ServerStream.RecvMsg(m); err != nil { return nil , err } return m, nil }
GO
client首先是client的接口和实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 type GreeterClient interface { SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error ) LotsOfReplies(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (Greeter_LotsOfRepliesClient, error ) LotsOfGreetings(ctx context.Context, opts ...grpc.CallOption) (Greeter_LotsOfGreetingsClient, error ) BidiHello(ctx context.Context, opts ...grpc.CallOption) (Greeter_BidiHelloClient, error ) }type greeterClient struct { cc grpc.ClientConnInterface }func NewGreeterClient (cc grpc.ClientConnInterface) GreeterClient { return &greeterClient{cc} }
GO
这里可以通过调用NewGreeterClient
创建一个client。
1 2 3 4 5 6 conn, err := grpc.Dial(*addr, grpc.WithInsecure())if err != nil { log.Fatalf("did not connect: %v" , err) }defer conn.Close() c := pb.NewGreeterClient(conn)
GO
GreeterClient
接口中也有很多结构体。接下来我们将分析分析其中的结构体。
Greeter_LotsOfRepliesClient & LotsOfReplies服务端流式数据, 同时还有对应方法的实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 type Greeter_LotsOfRepliesClient interface { Recv() (*HelloReply, error ) grpc.ClientStream }type greeterLotsOfRepliesClient struct { grpc.ClientStream }func (x *greeterLotsOfRepliesClient) Recv() (*HelloReply, error ) { m := new (HelloReply) if err := x.ClientStream.RecvMsg(m); err != nil { return nil , err } return m, nil }func (c *greeterClient) LotsOfGreetings(ctx context.Context, opts ...grpc.CallOption) (Greeter_LotsOfGreetingsClient, error ) { stream, err := c.cc.NewStream(ctx, &Greeter_ServiceDesc.Streams[1 ], "/pb.Greeter/LotsOfGreetings" , opts...) if err != nil { return nil , err } x := &greeterLotsOfGreetingsClient{stream} return x, nil }
GO
LotsOfGreetings & Greeter_LotsOfGreetingsClient1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 type Greeter_LotsOfGreetingsClient interface { Send(*HelloRequest) error CloseAndRecv() (*HelloReply, error ) grpc.ClientStream }type greeterLotsOfGreetingsClient struct { grpc.ClientStream }func (x *greeterLotsOfGreetingsClient) Send(m *HelloRequest) error { return x.ClientStream.SendMsg(m) }func (x *greeterLotsOfGreetingsClient) CloseAndRecv() (*HelloReply, error ) { if err := x.ClientStream.CloseSend(); err != nil { return nil , err } m := new (HelloReply) if err := x.ClientStream.RecvMsg(m); err != nil { return nil , err } return m, nil }func (c *greeterClient) LotsOfGreetings(ctx context.Context, opts ...grpc.CallOption) (Greeter_LotsOfGreetingsClient, error ) { stream, err := c.cc.NewStream(ctx, &Greeter_ServiceDesc.Streams[1 ], "/pb.Greeter/LotsOfGreetings" , opts...) if err != nil { return nil , err } x := &greeterLotsOfGreetingsClient{stream} return x, nil }
GO
BidiHello & Greeter_BidiHelloClient1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 func (c *greeterClient) BidiHello(ctx context.Context, opts ...grpc.CallOption) (Greeter_BidiHelloClient, error ) { stream, err := c.cc.NewStream(ctx, &Greeter_ServiceDesc.Streams[2 ], "/pb.Greeter/BidiHello" , opts...) if err != nil { return nil , err } x := &greeterBidiHelloClient{stream} return x, nil }type Greeter_BidiHelloClient interface { Send(*HelloRequest) error Recv() (*HelloReply, error ) grpc.ClientStream }type greeterBidiHelloClient struct { grpc.ClientStream }func (x *greeterBidiHelloClient) Send(m *HelloRequest) error { return x.ClientStream.SendMsg(m) }func (x *greeterBidiHelloClient) Recv() (*HelloReply, error ) { m := new (HelloReply) if err := x.ClientStream.RecvMsg(m); err != nil { return nil , err } return m, nil }
GO
所以几乎就是开箱可用,如果你想继续深入了解grpc。
可以关注grpc本身提供的一些功能。比如grpc的的https验证,grpc的拦截器等等。
关注序列化和反序列化的逻辑,关注rpc本身的实现。
参考教程
https://www.liwenzhou.com/posts/Go/gRPC/
https://www.liwenzhou.com/posts/Go/Protobuf3-language-guide-zh/