proto3语法
1. 指明版本
.proto文件中使用proto3的语法需要在开头声明:
syntax="proto3"
2. 定义消息
syntax = "proto3"; message AddUserReq { string name = 1; string password = 2; sint64 group_id = 3; }
消息的字段声明由4部分构成:字段修饰符 字段类型 字段名称 = 标志号
1) 字段修饰符
* singular : 默认值,该字段可以出现0次或者1次(不能超过1次)。
* repeated : 该字段可以重复任意多次(包括0次)。proto3中,repeated默认使用packed。
proto3中在语法层将required移除,singular是由optional改名而来。
2) 字段类型
.proto type | Notes | C++ type | Go type |
double | double | float64 | |
float | float | float32 | |
int32 | 使用变长编码,对于负值的效率很低,如果该域有可能有负值,使用sint64替代 | int32 | int32 |
int64 | int64 | int64 | |
uint32 | 使用变长编码 | uint32 | uint32 |
uint64 | 使用变长编码 | uint64 | uint64 |
sint32 | 使用变长编码,处理负值时比int32高效 | int32 | int32 |
sint64 | 使用变长编码,处理负值时比int64高效 | int64 | int64 |
fixed32 | 固定4个字节,如果数值总是比228大,此类型比uint32高效 | uint32 | uint32 |
fixed64 | 固定8个字节,如果数值总是比256大,此类型比uint64高效 | uint64 | uint64 |
sfixed32 | 固定4个字节 | int32 | int32 |
sfixed64 | 固定8个字节 | int64 | int64 |
bool | bool | bool | |
string | 一个字符串,必须是UTF-8编码或7-bit ASCII编码 | string | string |
bytes | 可能包含任意顺序的字节数据 | string | []byte |
默认值:
* string类型默认值是空字符串,不是null
* bytes类型默认是空bytes
* bool类型默认值是false
* 数字类型默认值是0
* 枚举类型默认值是第一个枚举值,即0
* repeated修饰的字段,默认值是空(在对应的编程语言中通常是一个空的list)
3) 标志号
每一个被定义在消息中的字段都会被分配一个唯一的标量,这些标量用于标志定义在二进制消息格式中的属性。标量一旦被定义就不允许在使用过程中再次被改变。
1~15的标志号在编码的时候会占用一个字节,16~2047的标志号则占用两个字节,所以应该为频繁出现的消息元素保留1~15的标志号。
保留标识符(reserved)可以避免其他人在未来使用不该使用的标志号。
message Foo { reserved 2, 15, 9 to 11; reserved "foo", "bar"; }
3. 枚举
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; }
Corpus枚举类型的第一个枚举值是0,每一个枚举值定义都会与一个常量映射,而这些常量的第一个常量必须为0。
4. 导入其它.proto中定义的消息
import "test/result.proto";
5. 包
可以为.proto文件指定包名,防止消息名冲突。
6. 服务定义
如果想在RPC中使用已经定义好的消息类型,可以在.proto文件中定一个消息服务接口,protocol buffer编译器会生成对应语言的接口代码。
service SearchService { // 方法名 方法参数 返回值 rpc Search(SearchRequest) returns (SearchResponse); }