注:内容翻译自官网文档 Language Guide (proto3) 中的 Defining A Message Type 一节
首先我们来看一个非常简单的例子. 让我们假设你想定义一个搜索请求消息格式, 每个搜索请求有一个查询字符串, 搜索结果的第几页/每页结果数量. 这里是你用来定义消息类型的.proto文件:
syntax = "proto3";
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
上面例子中, 所有字段都是Scalar Types/简单类型(下面会详细讲述), 包括两个int和一个string. 此外还可以支持复合类型包括枚举类型.
可以看到消息定义的每个字段都有一个唯一的数字型标签. 这个标签用于在消息的二进制格式中标识字段, 一旦消息类型被使用后不可以再修改.
注意标签的值在1和15之间时编码只需一个字节, 包括标识值和字段类型(可以在Protocol Buffer Encoding中找到更多信息). 标签在16到2047之间将占用两个字节. 因此应该将从1到15的标签分派给最频繁出现的消息元素. 记得保留一些空间给未来可能添加的频繁出现的元素.
可以指定的最小的标签值是1, 最大的是2的29次方-1, 即536870911. 另外19000到19999(FieldDescriptor::kFirstReservedNumber through FieldDescriptor::kLastReservedNumber)不能使用, 因为Protocol Buffers的实现自己保留这个标签段.
消息字段可以是下列之一:
由于历史原因, 简单数字类型的重复字段并没有编码为最有效率的方式. 新的代码应该使用特别选项[packed=true]来得到更有效率的编码. 例如:
repeated int32 samples = 4 [packed=true];
可以在Protocol Buffer Encoding中找到更多的关于packed encoding的信息.
可以在单个 .proto 文件中定义多个消息类型. 适用于定义多个相关消息, 例如, 如果你想定义应答消息格式来相应你的SearchResponse消息类型,你应该将它添加到同一个.proto文件.
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
message SearchResponse {
...
}
可以使用C/C++风格的"//"语法在.proto文件中添加注释.
message SearchRequest {
string query = 1;
int32 page_number = 2; // Which page number do we want?
int32 result_per_page = 3; // Number of results to return per page.
}
当你更新消息类型,需要彻底删除一个字段时, 或者注释掉它, 未来的用户在实现他们对这个类型的更新时可以重用这个标签数字. 这将导致言中的问题, 如果他们后来装载同一个.proto文件的老版本, 败落数据冲突, 隐私缺陷以及其他. 为了确保不发生这样的事情, 有一个方法时指明这个要删除的字段为保留字段. 如果未来任何用户试图私用这个字段标识符protocol buffer的编译器就是告警.
message Foo {
reserved 2, 15, 9 to 11;
reserved "foo", "bar";
}
注意: 不能在同一个保留字段声明中混合使用名字和标签数字
对.proto文件执行protocol buffer的编译器时, 编辑器会生成你所选语言的代码. 你可以用来处理你在文件中定义的消息类型, 包括读写字段值, 序列化消息到输出流, 和从输入流中解析消息.
你可以通过所选语言的教程(proto3版本即将到来)来找到更多关于如何使用每个语言的API的信息. 对于API的细节, 请看相应的API参考手册(proto3版本即将到来).
注: proto3版本的API参考手册已经放出,点击这里查看中文翻译版本