Protobuf
Contents
Protobuf
gRPC推荐使用proto3,这里只介绍常用语法,按照官方文档的结构翻译,英文水平有限,复杂的部分果断放弃,更多高级使用姿势请参考官方文档
Message定义
一个message
类型定义描述了一个请求或响应的消息格式,可以包含多种类型字段。
例如定义一个搜索请求的消息格式SearchRequest
,每个请求包含查询字符串、页码、每页数目。每个字段声明以分号结尾。
syntax = "proto3";
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
分配Tags
消息的定义中,每个字段都有一个唯一的数值标签。这些标签用于标识该字段在消息中的二进制格式,使用中的类型不应该随意改动。其中,[1-15]内的标识在编码时占用一个字节,包含标识和字段类型。[16-2047]之间的标识符占用2个字节。建议为频繁出现的消息元素分配[1-15]间的标签。如果考虑到以后可能或扩展频繁元素,可以预留一些。
最小的标识符可以从1开始,最大到229 - 1,或536,870,911。不可以使用[19000-19999]之间的标识符, Protobuf协议实现中预留了这些标识符。在.proto文件中使用这些预留标识号,编译时会报错。
字段规则
- 单数形态:一个message内同名单数形态的字段不能超过一个
- repeated:前置
repeated
关键词,声明该字段为数组类型 proto3
不支持proto2
中的required
和optional
关键字
添加注释
向.proto
文件中添加注释,支持C/C++风格双斜线//
单行注释。
syntax = "proto3"; // 协议版本声明
// SearchRequest 搜索请求消息
message SearchRequest {
string query = 1; // 查询字符串
int32 page_number = 2; // 页码
int32 result_per_page = 3; // 每页条数
}
保留字段名与Tag
可以使用reserved
关键字指定保留字段名和标签。
message Foo {
reserved 2, 15, 9 to 11;
reserved "foo", "bar";
}
基本数据类型
.proto | C++ | Java | Python | Go | Ruby | C# |
---|---|---|---|---|---|---|
double | double | double | float | float64 | Float | double |
float | float | float | float | float32 | Float | float |
int32 | int32 | int | int | int32 | Fixnum or Bignum | int |
int64 | int64 | long | ing/long[3] | int64 | Bignum | long |
uint32 | uint32 | int[1] | int/long[3] | uint32 | Fixnum or Bignum | uint |
uint64 | uint64 | long[1] | int/long[3] | uint64 | Bignum | ulong |
sint32 | int32 | int | intj | int32 | Fixnum or Bignum | int |
sint64 | int64 | long | int/long[3] | int64 | Bignum | long |
fixed32 | uint32 | int[1] | int | uint32 | Fixnum or Bignum | uint |
fixed64 | uint64 | long[1] | int/long[3] | uint64 | Bignum | ulong |
sfixed32 | int32 | int | int | int32 | Fixnum or Bignum | int |
sfixed64 | int64 | long | int/long[3] | int64 | Bignum | long |
bool | bool | boolean | boolean | bool | TrueClass/FalseClass | bool |
string | string | String | str/unicode[4] | string | String(UTF-8) | string |
bytes | string | ByteString | str | []byte | String(ASCII-8BIT) | ByteString |
Message嵌套
message SearchResponse {
message Result {
string url = 1;
string title = 2;
repeated string snippets = 3;
}
repeated Result results = 1;
}
message Outer { // Level 0
message MiddleAA { // Level 1
message Inner { // Level 2
int64 ival = 1;
bool booly = 2;
}
}
message MiddleBB { // Level 1
message Inner { // Level 2
int32 ival = 1;
bool booly = 2;
}
}
}
Protobuf —> Go
proto中的message
对应go中的struct
,全部使用驼峰命名规则。嵌套定义的message
,enum
转换为go之后,名称变为Parent_Child
结构。
// Test 测试
message Test {
int32 age = 1;
int64 count = 2;
double money = 3;
float score = 4;
string name = 5;
bool fat = 6;
bytes char = 7;
// Status 枚举状态
enum Status {
OK = 0;
FAIL = 1;
}
Status status = 8;
// Child 子结构
message Child {
string sex = 1;
}
Child child = 9;
map<string, string> dict = 10;
}
// Status 枚举状态
type Test_Status int32
const (
Test_OK Test_Status = 0
Test_FAIL Test_Status = 1
)
// Test 测试
type Test struct {
Age int32 `protobuf:"varint,1,opt,name=age" json:"age,omitempty"`
Count int64 `protobuf:"varint,2,opt,name=count" json:"count,omitempty"`
Money float64 `protobuf:"fixed64,3,opt,name=money" json:"money,omitempty"`
Score float32 `protobuf:"fixed32,4,opt,name=score" json:"score,omitempty"`
Name string `protobuf:"bytes,5,opt,name=name" json:"name,omitempty"`
Fat bool `protobuf:"varint,6,opt,name=fat" json:"fat,omitempty"`
Char []byte `protobuf:"bytes,7,opt,name=char,proto3" json:"char,omitempty"`
Status Test_Status `protobuf:"varint,8,opt,name=status,enum=test.Test_Status" json:"status,omitempty"`
Child *Test_Child `protobuf:"bytes,9,opt,name=child" json:"child,omitempty"`
Dict map[string]string `protobuf:"bytes,10,rep,name=dict" json:"dict,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
}
// Child 子结构
type Test_Child struct {
Sex string `protobuf:"bytes,1,opt,name=sex" json:"sex,omitempty"`
}