跳至主要內容

gRPC的使用

pptg大约 2 分钟

1. MacOS的环境配置

  1. 下载地址: protocolbuffers/protobufopen in new window
  2. 解压
  3. 移动protoc到bin下
pptg:~/ $ cd /Users/pptg/Downloads/protoc-28.0-rc-2-osx-aarch_64/bin
pptg:bin/ $ ls                                                       [16:54:59]
protoc
pptg:bin/ $ mv protoc /usr/local/bin                                 [16:55:00]
  1. protoc --version尝试打开,报垃圾软件,去设置>隐私与安全>仍旧打开
  2. 重试一下,ok了
pptg:bin/ $ protoc --version                                         [17:00:12]
libprotoc 28.0-rc2

2. Golang配置

# 安装核心库
go get google.golang.org/grpc
# 安装代码生成器
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

3. 生成文件解读

然后依旧是照着网上的教程open in new window试一下demo, 这里照着敲一敲就ok了

这里以自己的理解来记录一下对xxxx_grpc.pb.go的理解,因为第一次看的时候还是挺糊涂的,不知道为什么网上没有讲解,难道只有我一个人迷糊吗 TAT

3.1 客户端API接口

首先,这个文件定义了客户端的API接口, 这个还是比较好理解的,为我们自动生成了proto文件定义的接口而已

// 定义服务
type GreeterClient interface {
	// SayHello 方法
	SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloResponse, error)
}

type greeterClient struct {
	cc grpc.ClientConnInterface
}

func NewGreeterClient(cc grpc.ClientConnInterface) GreeterClient {
	return &greeterClient{cc}
}

func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloResponse, error) {
	cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
	out := new(HelloResponse)
	err := c.cc.Invoke(ctx, Greeter_SayHello_FullMethodName, in, out, cOpts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

这里在使用的时候可以直接调用NewGreeterClient()来获取对象,并继续调用SayHello()发起请求

3.2 服务端API接口

服务端不同于客户端,对于客户端来说,可以不调用服务端的某些方法,但是对于服务端来说,如果客户端调用了服务端没有实现的方法,则需要予以相应的提示

于是grpc自动为所有的方法生成了一个默认的实现,并将这个作为匿名字段来解决这个问题

// 定义服务
type GreeterServer interface {
	// SayHello 方法
	SayHello(context.Context, *HelloRequest) (*HelloResponse, error)
	mustEmbedUnimplementedGreeterServer()
}

type UnimplementedGreeterServer struct{}

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

这里再看一下需要我们自己实现的注册服务的代码

pb.RegisterGreeterServer(s, &GreetServer{})

type GreetServer struct {
	pb.UnimplementedGreeterServer
}

// 省略了实现方法

如果将pb.UnimplementedGreeterServer去掉,则pb.RegisterGreeterServer会报错

Cannot use '&GreetServer{}' (type *GreetServer) as the type GreeterServer Type cannot implement 'GreeterServer' as it has a non-exported method and is defined in a different package

因为这个mustEmbedUnimplementedGreeterServer()的首字母是小写的,无法这样去直接实现这个接口,所以必须在结构体内部用匿名的pb.RegisterGreeterServer