Protocol Buffer
google 出品的一种数据交换格式, 缩写为 protobuf.
protobuf 分为编译器和运行时两部分. 编译器直接使用预编译的二进制文件即可, 可以从 releases 上下载.
protobuf 运行时就是不同语言对应的库, 以 Golang 为例:
go get github.com/golang/protobuf/protoc-gen-go
语法
syntax = "proto3";
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
message 的结构非常类似于各种语言中的 struct, dict 或者 map
每个字段包括三个部分, 类型, 字段名和字段编号.
同一个 message 中字段编号应该是唯一的
注释语法是 // 和 /* ... */.
syntax = "proto3";
message Foo {
reserved 2, 15, 9 to 11;
reserved "foo", "bar";
}
message Test4 {
repeated int32 d = 4 [packed=true];
}
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
enum Corpus {
UNIVERSAL = 0;
WEB = 1;
IMAGES = 2;
LOCAL = 3;
NEWS = 4;
PRODUCTS = 5;
VIDEO = 6;
}
Corpus corpus = 4;
}
enum EnumAllowingAlias {
option allow_alias = true;
UNKNOWN = 0;
STARTED = 1;
RUNNING = 1; // RUNNING 是 STARTED 的别名
}
使用 reserved 注明已被废弃的字段编号和字段名称.
使用 repeated 可以指定重复字段, 即数组.
使用 enum 定义枚举类型. 每个枚举定义都必须包含一个映射值为 0 的常量作为第一个元素.可以使用 allow_alias 选项允许枚举值的别名.
syntax = "proto3";
message SearchResponse {
repeated Result results = 1;
}
message Result {
string url = 1;
string title = 2;
repeated string snippets = 3;
}
类型也可以嵌套使用.
syntax = "proto3";
import "myproject/other_protos.proto";
import public "new.proto";
使用 import 可以导入外部定义.
使用 import public 可以传递导入依赖, 通常用于被导入的 proto 文件需要更改的情况下.
protocol 编译器搜索的位置是命令行参数中的 -I/--proto_path
syntax = "proto3";
import "google/protobuf/any.proto";
message ErrorStatus {
string message = 1;
repeated google.protobuf.Any details = 2;
}
Any 类型可以让你可以在没有它们的 proto 定义时, 将 messages 用作内嵌的类型. 一个 Any 包括任意的二进制序列化的 message, 就像 bytes 类型那样, 以及用作该类型的全局唯一的标识符 URL.
syntax = "proto3";
message SampleMessage {
oneof test_oneof {
string name = 4;
SubMessage sub_message = 9;
}
}
如果你有一个 message 包括许多字段, 但同时最多只有一个字段会被设置, 可以使用 Oneof 特性来节省内存. Oneof 字段和普通的字段没有区别, 除了所有这些 Oneof 字段共享内存, 且同时只能由一个字段被设置. 你可以使用特殊的 case() 或 WhichOneof() 方法检查哪个字段被设置了, 具体方法名称取决于实现的语言.
syntax = "proto3";
map<key_type, value_type> map_field = N;
map<string, Project> projects = 3;
使用 map 可以创建关联映射.key_type 可以是 integral 或 string 类型, 即 scalar 类型中除了 floating point types 和 bytes 以外的类型. value_type 可以是除 map 以外的任何类型.
syntax = "proto3";
package foo.bar;
使用 package 可以设置命名空间, 防止 message 类型冲突. 在Golang中: package 用作 Go 包名, 除了你使用 option go_package 显式声明包名
syntax = "proto3";
service SearchService {
rpc Search (SearchRequest) returns (SearchResponse);
}
定义服务。
以上内容来自:https://zhuanlan.zhihu.com/p/92559559