使用protoc编译.proto文件
Protoc介绍
protoc是protobuf文件(.proto)的编译器,我们可以借助这个工具把 .proto 文件转译成各种编程语言对应的源码,包含数据类型定义、调用接口等。protoc在设计上把protobuf和不同的语言解耦,底层用c++来实现protobuf结构的存储,然后通过插件的形式来生成不同语言的源码。源码中包含的插件有 csharp、java、js、objectivec、php、python、ruby等多种。
安装针对go的protoc插件
- protoc本身并不支持Golang,需要额外安装对应的插件。
- 方法1,使用go install
@latest安装 - 方法2,在一个已经包含go.mod文件的项目里使用go get
- 方法1,使用go install
-
安装成功后,会在
$GOPATH/bin
目录下生成两个2进制文件protoc-gen-go
protoc-gen-go-grpc
注:这时候执行
protoc --go_out=. --go-grpc_out=. *.proto
时,可能出现--go_out: protoc-gen-go: Plugin failed with status code 1
的报错,这是由于$GOPATH/bin
目录没有添加到系统环境变量里。
实践
准备一个.proto文件
- 新建gRPC项目,使用
go mod init
初始化,创建pb文件夹,新建hello.proto文件 -
指定
syntax,package,option go_package
,分别代表protobuf版本,包名,编译生成的.pb.go
文件目录option go_package = "./proto/hello"
:代表在protoc编译时,在--go_out
指定的目录下自动生成proto/hello
文件夹,同时在该文件夹下生成的.pb.go
文件的包名是hello
。- 可以通过如下格式指定包名
option go_package = "./proto/hello;helloRename"
;表示生成的.pb.go
文件的包名是helloRename
。
定义service和message
service
对应golang中的接口-
message
对应golang中的结构体// The greeter service definition. service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply) {} } // The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings message HelloReply { string message = 1; }
完整的 hello.proto
syntax = "proto3";
package pb;
option go_package = "./proto/hello";
// The greeter service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
使用protoc编译
- 在
gRPC/pb
目录下使用如下命令进行编译 - 生成对应的
.pb.go
和_grpc.pb.go
两个文件,前者主要是对message
生成对应的结构体和方法,后者生成gRPC
,主要是对service
生成对应的interface
和方法
go_out=.
指定生成的pb.go
文件所在目录(如果没有该目录,需要手动提前创建),.
代表当前protoc执行目录,结合.proto
文件中的option go_package
,其最终的生成文件目录为go_out指定目录/go_package指定目录
。go-grpc_out
针对_grpc.pb.go
文件,作用同上。- 另外官网文档里还有一个
--go_opt=paths=source_relative
,其含义代表生成的.pb.go
文件路径不依赖于.proto
文件中的option go_package
配置项,直接在go_out
指定的目录下生成.pb.go
文件(.pb.go
文件的package
名还是由option go_package
决定)。 --go-grpc_opt=paths=source_relative
,针对_grpc.pb.go
文件,作用同上。
总结
- 模块
github.com/golang/protobuf
由google.golang.org/protobuf
取代 - 当前版本编译时,之前的方法
protoc --go_out=plugins=grpc:. *.proto
不再使用,转而用protoc --go_out=. --go-grpc_out=. ./hello.proto
代替。有如下提示