02. November 2021
用Protobuf定义RPC和HTTP服务

plugins
| 插件 | 功能 | 版本 | 备注 |
|---|---|---|---|
protoc | 调用编译程序 | v3.17.3 | |
protoc-gen-go | 编译message结构体 | - | |
protoc-gen-go-grpc | 编译grpc接口 | v1.0.1 | |
protoc-gen-grpc-gateway | 编程http接口 | - | |
protoc-gen-swagger | 生成swagger文档 | - | |
protoc-gen-validate | 生成validate格式校验 | v0.6.2 | #570 |
sample
1
2syntax = "proto3";
3
4package message;
5option go_package = "/;gen";
6
7import "google/api/annotations.proto";
8
9service Serv {
10 rpc SayHelloWorld (request) returns (response) {
11 option (google.api.http) = {
12 get: "/helloworld"
13 };
14 };
15}
16
17message request {}
18
19message response {
20 string raw = 1;
21}
go_package
go_package指定生成的go文件的包名,选项的值分为两部分,分号之前表示生成文件的路径,路径的/根目录是指protoc编译时选项--go_out指定的位置,分号之后的第二部分表示生成文件的包名
package
package表示当前proto文件的包
import
google/api/annotations.proto是编译http接口必须依赖的文件,引用了这个文件直接编译会出现错误,因为protoc找不到这个文件的位置,import的包位置是从根目录开始的文件位置,这里的根目录是指$GOPATH/src所在的路径,解决的方法有两种,可以把文件拷贝到对应位置,也可以用protoc的选项来添加可选根目录的位置,他是一个数组,通过--proto_path可以指定根目录的位置,如果想指定多个位置,用:分隔开就可以了,像PATH一样,这个选项的设置是覆盖的,如果使用,必须指定出所有需要的位置
build
1PROTO_SRC=./gen.proto
2
3message:
4 protoc --go_out=. --proto_path=.:$$GOPATH/src:$$GOPATH/src/github.com/googleapis/googleapis $(PROTO_SRC)
5
6grpc:
7 protoc --go-grpc_out=require_unimplemented_servers=false:. --proto_path=.:$$GOPATH/src:$$GOPATH/src/github.com/googleapis/googleapis $(PROTO_SRC)
8
9gateway:
10 protoc --grpc-gateway_out=. --proto_path=.:$$GOPATH/src:$$GOPATH/src/github.com/googleapis/googleapis $(PROTO_SRC)
11
12swagger:
13 protoc --swagger_out=. --proto_path=.:$$GOPATH/src:$$GOPATH/src/github.com/googleapis/googleapis $(PROTO_SRC)
14
15validate:
16 protoc --validate_out=lang=go:$(OUT_ROOT_PATH) --proto_path=.:$$GOPATH/src:$$GOPATH/src/github.com/googleapis/googleapis $(PROTO_SRC)
17
18.PHONY: message grpc gateway swagger validate
require_unimplemented_servers=false
新版本的protoc-gen-go移除了生成grpc代码的功能,生成grpc功能独立成为一个工具protoc-gen-go-grpc,在v1.0.0和v1.1.0上通过默认方式产生的grpc代码都会包含一个无法实现的接口mustEmbedUnimplementedServServer,通过require_unimplemented_servers=false可以阻止生成这个接口,原因得看这里