一、文件名:*.proto
二、PB文件引用:
import "myprojce/other_protos.proto";
三、文件内容:
1.消息类型
message msgName{
require string query=1;
optional int32 page_number=2;
}
说明:
1)一个.proto文件中可以定义多个message类型。
2)同时,如果1个.proto文件定义了多个具有不同依赖的message,会导致依赖膨胀;建议每个文件包含尽可能少的message。
2.数据类型
标量类型:
.proto 类型 | 说明 | C++ 数据类型 | Java 数据类型 | Python 数据类型 | Go 数据类型 |
---|---|---|---|---|---|
double | double | double | float | *float64 | |
float | float | float | float | *float32 | |
int32 |
1)使用可变长度编码; 2)对负数编码效率较低,若字段可能为负值,请使用sint32。 | int32 | int | int | *int32 |
int64 |
1)使用可变长度编码; 2)对负数编码效率较低,若字段可能为负值,请使用sint64。 | int64 | long | int/long[3] | *int64 |
uint32 | 使用可变长度编码 | uint32 | int[1] | int/long[3] | *uint32 |
uint64 | 使用可变长度编码; | uint64 | long[1] | int/long[3] | *uint64 |
sint32 |
1)使用可变长度编码; 2)有符号int,编码负数时比int32更高效。 | int32 | int | int | *int32 |
sint64 |
1)使用可变长度编码; 2)有符号int,编码负数时比int64更高效。 | int64 | long | int/long[3] | *int64 |
fixed32 |
1)固定4字节; 2)如果数值经常大于228,则比uint32的编码效率高。 | uint32 | int[1] | int/long[3] | *uint32 |
fixed64 |
1)固定8字节; 2)如果数值经常大于256,则比uint64的编码效率高。 | uint64 | long[1] | int/long[3] | *uint64 |
sfixed32 | 固定4字节 | int32 | int | int | *int32 |
sfixed64 | 固定8字节 | int64 | long | int/long[3] | *int64 |
bool | bool | boolean | bool | *bool | |
string |
字符串,必须包含UTF-8编码或7位ASCII文本。 | string | String | str/unicode[4] | *string |
bytes | 可包含任意的字节序列 | string | ByteString | str | []byte |
3.字段序号
举例:
require int32 samples=4; //4位字段序号
说明:message中的每个字段都有唯一序号。
作用:用于识别二进制message中的字段。
注意:
1)序号最小值为1,最大值为2^29-1(536870911);
2)不能使用19000~19999之间的数字,因为它们是为PB实现保留的。其中19000为FieldDescriptor::kFirstReservedNumber,19999为FieldDescriptor::kLastReservedNumber。如果使用了,PB编译器会报错;同样也不能重复使用已保留的字段序号。
3)消息已被使用后不能修改序号。
4)为频繁使用的消息成员保留字段号1~15。
编码格式:
1)1~15的序号用1个字节来编码(并包含字段序号和字段类型);
2)16~2017的序号暂用2个字节;
4.字段规则:
require int32 page_size=1;
required:message中必有的字段
optional:message中可以有0或1个这个字段(不超过1个),若该字段不存在,则解析为改字段的默认值
repeated:该字段在message中可以重复多次(包含0次),并保留重复值的顺序
注:该类型的字段编码效率不高,新代码需使用特殊选项[packed=true]来提高编码效率。例如:
repeated int32 samples = 4 [packed=true];
5.命名空间:
package pkg_name;
1)对于java,解析为包名;
2)对于c++,解析为namespace;
6.注释:
格式://或/**/
7.预留字段:
问题:若更新message后删除或注释了某个字段,老协议版本用户又使用了这个字段,会导致数据损坏、隐私泄露等问题。
解决方法:指定已删除字段的序号为预留,这样如果有用户尝试使用该字段标识符时,PB编译器会报错。使用例子如下:
message Foo {
reserved 2, 15, 9 to 11;
reserved "foo", "bar";
}
注意:不能将字段名和字段号混合在同一个预留
声明
8.字段默认值:
optional int32 page_size=1 [default=10];
使用说明:
1)若该字段不存在,则解析为默认值10;
2)若为设置默认值,则使用标量类型的默认值:
字符串:空;
bool:false;
数字类型:0;
枚举类型:定义列表中的第一个值
9.枚举类型:
enum MsgCmd{
MSG_LOGIN=1;
MSG_LOGOUT=2;
MSG_GET_EMAIL=3;
}
说明:枚举常量数值范围必须在32位整数内。
四、代码生成:
PB编译器可将proto文件转换成c++、java、python、go等语言的代码,包含get、set字段的值,message的序列化和反序列化。
- C++:.h和.cc文件
- java:为每个message生成一个.java文件,以及用于创建message类实例的Builder类。
- python:待补充
- go: