Protocol Buffers 官方给出的一些使用建议、部分细节说明以及一些配套工具介绍记录在这里。
入门教程 Protocol Buffers Tutorials,协议语法要点见 tag: protobuf。
Style Guide 是 Protocol Buffers 给出的风格建议。
1. License header (if applicable)
2. File overview
3. Syntax
4. Package
5. Imports (sorted)
6. File options
7. Everything else
message SongServerRequest {
optional string song_name = 1;
}
enum FooBar {
FOO_BAR_UNSPECIFIED = 0;
FOO_BAR_FIRST_VALUE = 1;
FOO_BAR_SECOND_VALUE = 2;
}
service FooService {
rpc GetSomething(GetSomethingRequest) returns (GetSomethingResponse);
rpc ListSomething(ListSomethingRequest) returns (ListSomethingResponse);
}
Design Patterns for Dealing with Protocol Buffers 给出了部分场景下的使用说明/建议。
Protobuf Buffers 不适合传输大段数据,如果需要发送的 message 超过 1MB,需要考虑使用其它方式。
可以用下面的方式实现自描述的消息(Google 内部没有遇到需要使用自描述消息的情形):
syntax = "proto3";
import "google/protobuf/any.proto";
import "google/protobuf/descriptor.proto";
message SelfDescribingMessage {
// Set of FileDescriptorProtos which describe the type and its dependencies.
google.protobuf.FileDescriptorSet descriptor_set = 1;
// The message and its type, encoded as an Any message.
google.protobuf.Any message = 2;
}
Protocol Buffer Wire Format 介绍了 protobuf 的编码方式,即二进制格式, 按需了解。
Proto 文件编写完成后,需要再将 .proto 文件转化成目标语言的代码文件或 object 文件。 Protocol Buffer 提供了编译命令 protoc。protoc 自身内置支持 cpp/csharp/java 等语音。还没内置支持的语言,可以用插件辅助编译:Compiler Plugins 。有很多第三方开发维护的 addon: Third-Party Add-ons。
编译后生成的代码通常会引用对应语言的 runtime 库:Protobuf Runtime。
Google 开发了 protobuf-go 项目实现对 go 语言的支持。protobuf-go 实现了插件 protoc-gen-go,同时也是 go 版本的 protobuf runtime 库: google.golang.org/protobuf。
protoc-gen-go 用 go 或者 mac 的 brew 命令安装:
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
# 或者
brew install protoc-gen-go
将 proto 文件编译成 go 代码,–go_out 即编译成 go 代码的意思,protoc 会搜寻 protoc-gen-go 插件:
protoc -I=$SRC_DIR --go_out=$DST_DIR $SRC_DIR/*.proto
如果要为 protoc-gen-go 传入参数,用 go_opt=X=xx 的方式指定。比如下面指定参数 paths=source_relateive。paths 是用来设置生成的的代码的位置,详情见 Compiler Invocation。
protoc -I=$SRC_DIR --go_opt=paths=source_relative --go_out=$DST_DIR $SRC_DIR/*.proto
也可以用 –plugin 明确指定要使用的插件:
--plugin=EXECUTABLE Specifies a plugin executable to use.
Normally, protoc searches the PATH for
plugins, but you may specify additional
executables not in the path using this flag.
Additionally, EXECUTABLE may be of the form
NAME=PATH, in which case the given plugin name
is mapped to the given executable even if
the executable's own name differs.
proto 文件还可以编译成支持 proto 的 rpc 框架的代码,比如 gRPC,还有 RPC Implementations 等。 grpc 框架本身也是支持多语言的,这里以 go 语言为例,需要同时安装 protoc-gen-go 和 protoc-gen-go-grpc 两个插件:
go install google.golang.org/protobuf/cmd/[email protected]
go install google.golang.org/grpc/cmd/[email protected]
# 或者
brew install protoc-gen-go protoc-gen-go-grpc
编译成 grpc 代码:
protoc --go_out=. --go-grpc_out=. helloworld/helloworld.proto
一个可以解析 proto 文件的 package:github.com/jhump/protoreflect。