proto3相较于proto2支持更多语言且语法更为简洁,proto3去除了一些复杂的语法和特性,更加强调约定而弱化语法。
- 删除原始值类型的presence字段逻辑
- 删除required字段及默认值
- 移除unknown关键字
- 去掉extensions类型,使用Any类型替换。
- 针对未知枚举值的固定语法
- 增加maps代码生成支持map
- 添加表示时间、动态数据等的标准类型
- 替换二进制编码明确JSON编码
定义消息
例如:定义一个搜索请求的消息格式,每个请求含有查询字符串、页码、分页条数。
//声明包名:package 命名空间;
package ns;
//语法说明:syntax = "语法版本";
syntax = "proto3";
//消息格式:message + 消息名称
message SearchRequest{
//字段:字段限制+字段类型+字段名称 = 数值标签
string query = 1;
int32 page = 2;
int32 pagesize = 3;
}
声明包名
可以为.proto
文件新增一个可选的package
声明符,用于防止不同消息类型产生的命名冲突。
package jc.com;
message SearchRequest
{
string query = 1;
}
在其它消息格式定义可以使用【包名+消息名】来定义域的类型
message Open
{
required jc.com.SearchRequest rq = 1;
}
字段格式
字段限制 + 消息类型 + 字段名称 = 数值标签;
字段限制
字段限制 | 描述 |
---|---|
required | 必须赋值的字段 |
optional | 可有可无的字段 |
repeated | 可重复的字段(变长字段) |
消息字段可以使用两种规则进行描述
字段规则 | 含义 | 描述 |
---|---|---|
single | 单一的 | 0个或1个,不用在字段定义中指出。 |
repeated | 重复的 | 0个到多个,需要在字段定义中指出。 |
比如:一个用户只能有一个固定的账户,但可以有多个不同的昵称,也可以没有。
package ns;
syntax = "proto3";
message User{
string account = 1;
string username = 2;
repeated string nickname = 3;
string realname = 4;
}
消息类型
消息类型 | 默认值 | 描述 |
---|---|---|
double | 0 | 双精度浮点数 |
float | 0 | 单精度浮点数 |
int32 | 0 | 使用可变长度编码,编码负数的效率低,若字段有负值改用sint32。 |
int64 | 0 | 使用可变长度编码,编码负数的效率低,若字段有负值改用sint64。 |
uint32 | 0\使用可变长度编码 | |
uint64 | 0 | 使用可变长度编码 |
sint32 | 0 | 使用可变长度编码,比常规int32更有效编码负数。 |
sint64 | 0 | 使用可变长度编码,比常规int64更有效编码负数。 |
fixed32 | 0 | 占用4个字节,值大于228时比uint32更有效。 |
fixed64 | 0 | 占用8个字节,如果值大于256则比uint64更有效。 |
sfixed32 | 0 | 占用4个字节 |
sfixed64 | 0 | 占用8个字节 |
bool | false | - |
string | "" | 字符串必须始终包含UTF-8编码或7位ASCII文本 |
bytes | 可以包含任意字节序列 |
数值标签
- 消息结构中每个字段都具有唯一的数字标识(数值类型的编号标签),用来在二进制格式中识别字段。
- 消息一旦开始使用,数字标识就不应该在被修改。
- 最小的数值标签为1,最大的数值标签为536,870,911。
- 当消息被序列化为二进制后,编号1到15会使用1个字节编码,16到2047使用2个字节编码,因此编号1到15一般会留给频繁使用的字段。
- 编号19000~19999是系统预留的,不可使用。
编号范围 | 占用字节 | 描述 |
---|---|---|
1~15 | 1 | 高频字段 |
16~2047 | 2 | 普通字段 |
19000~19999 | 系统预留 |