1

更方便的在微信公众号阅读文章可以关注公众号:海生的go花园
图片

一、介绍

在第五章,我们学习了.pb.go文件
《go入门grpc》第五章:protoc生成的.pb.go文件解读
本章我们学习下protoc --go-grpc_out 命令生成的_grpc.pb.go文件。
我们以hello.proto文件为例,代码如下:

syntax = "proto3";
package hello;
import "google/protobuf/timestamp.proto";

option go_package = "github/hisheng/grpc-demo1/api";

service Say {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
  google.protobuf.Timestamp last_updated = 2;
}

使用protoc --go-grpc_out命令生成了 hello_grpc.pb.go文件。

package api
......
type SayClient interface {
    SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error)
}
......
type SayServer interface {
    SayHello(context.Context, *HelloRequest) (*HelloReply, error)
    mustEmbedUnimplementedSayServer()
}
......

主要有三部分

  1. package
  2. Server服务端接口
  3. Client客户端接口

二、Server服务端接口

_grpc.pb.go自动生成的文件,提供了一个注册服务的方法RegisterSayServer
我们写微服务server端,是启动一个grpc服务器,然后通过RegisterSayServer方法,把 各种服务注册进去。

// SayServer 是 Say service提供api的接口
// 所有的自定义service,都必须把UnimplementedSayServer嵌入
// 才能调用SayServer接口
type SayServer interface {
    SayHello(context.Context, *HelloRequest) (*HelloReply, error)
    mustEmbedUnimplementedSayServer()
}

// UnimplementedSayServer 最原始的SayServer接口实现。
type UnimplementedSayServer struct {
}

func (UnimplementedSayServer) SayHello(context.Context, *HelloRequest) (*HelloReply, error) {
    return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented")
}
func (UnimplementedSayServer) mustEmbedUnimplementedSayServer() {}

func RegisterSayServer(s grpc.ServiceRegistrar, srv SayServer) {
    s.RegisterService(&Say_ServiceDesc, srv)
}

server 端提高了 UnimplementedSayServer,我们自己实现,这个相当于是基类。需要内嵌到我们的结构体中。

server 定义了一个对外可以使用api接口的接口SayServer
然后再生成了一个 最底层实现UnimplementedSayServer,供我们自己实现的时候,嵌入进去,然后重写其方法。
思考:

为什么要 UnimplementedSayServer ?

因为go里面,没有继承这一个 原语,我们通过嵌入的方式,实现类似的效果。
如果没有UnimplementedSayServer,那么其他的地方也写了一个 SayHello方法,但它加入是供http调用的,那么它算不算 实现了SayServer接口呢?
通过加 UnimplementedSayServer,我们知道了,它是grpc,没加就不算grpc,就很一目了然。

三、Client客户端接口

SayClient 是 SayService 的 客户端。
主要包括定义了一个SayClient接口,以及一个sayClient结构体。
sayClient结构体实现了SayClient接口。
对外提供一个 NewSayClient()来生成初始化SayClient客户端。

type SayClient interface {
   SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error)
}

type sayClient struct {
   cc grpc.ClientConnInterface
}

func NewSayClient(cc grpc.ClientConnInterface) SayClient {
   return &sayClient{cc}
}

func (c *sayClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) {
   out := new(HelloReply)
   err := c.cc.Invoke(ctx, "/hello.Say/SayHello", in, out, opts...)
   if err != nil {
       return nil, err
   }
   return out, nil
}

海生
104 声望32 粉丝

与黑夜里,追求那一抹萤火。