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);
}