proto3语言指南
翻译+整理,翻阅的时候方便些,只翻译了可能用到的。
这个指南描述怎么使用 protocol buffer 语言来描述数据,包括 proto 文件语法和如何生成数据访问类。支持的是 proto3 版本
定义一个消息类型(Message Type)
先来看一个非常简单的例子。定义一个搜索请求消息格式,每个请求有一个查询字符串,搜索结果的指定页和每页的结果数量。下面是定义消息类型的 .proto 文件
一个 .proto 文件可以定义多个消息类型。
syntax = "proto3"; |
第一行指定版本,默认是 proto2,必须是文件的第一个非空,非注释行。SearchRequest 定义了这个消息所需要的数据,包括三个字段(键值对),每个字段都有一个名字和类型。
使用c/c++风格的注释
指定字段类型
上面的例子里面所有字段都是标量类型:两个整数和一个字符串。这里可以包括复合类型,包括枚举和其他信息类型。
分配标识
上面例子中每个字段都有一个唯一的数字标识。这些标识是用来在二进制格式消息中区分字段的,并且一旦使用就不应该更改。
注意:1-15标识占1个字节,包括标识数字和字段类型。16-2047占2个字节。
你应该保留1-15标识给经常出现的信息元素使用,同时注意留一些标识给将来可能增加的频繁元素。
最小的标识是1,最大的是$2^29 - 1$, 或者 536,870,911,保留标识:19000 - 19999。
指定字段规则
消息字段可以是下面的一种:
- singular: 结构良好的消息可以有0-1个这个字段(但是不能多于一个)
- repeated: 这个字段可以重复任何次数包括0,重复的值得顺序会被保留。
在 proto3 中数字类型的 repeated 字段默认使用 packed 编码
保留字段
如果删除了一个字段,最好定义为保留字段,这样就不会被重复使用,造成兼容性问题。
message Foo { |
这里注意不能在一个 reserved 字段混用名字和数字
从 .proto 文件生成什么
当你使用 protocol Buffer(后面简写pb) 编译器编译 .proto 文件时编译器会生成存取,序列化代码。
对于 go 会生成 .pb.go 文件
默认值
当解析一个消息是,如果编码消息没有指定一个 singular 元素,那么在解析出来的对象中使用默认值。
- strings 空字符串
- bytes 空
- bools false
- numberic 0
- enums 第一个定义的enum值,0
注意,解析之后,是无法知道字段是设置为 false 还是因为没有设置才是默认值 false 的。
枚举
定义一个消息类型时,可能想要某个字段只在预定义的范围内取值。例如:在 SearchRequest 增加一个 corpus 字段,取值可以为 UNIVERSAL, WEB, IMAGES, LOCAL, NEWS, PRODUCTS, VIDEO。
message SearchRequest { |
可以通过定义 allow_alias = true 来支持不同枚举常量可以有相同的值。
enum EnumAllowingAlias { |
枚举常量取值范围在32位置整数内。负值效率不高不推荐。
可以在消息内部定义枚举,也可以在外部定义(可以在 .proto 文件的任何消息中使用)。
也可以在不同消息中引用枚举,语法:MessageType.EnumType
使用其他消息类型
可以使用其他消息类型作为字段。例如:在 SearchResponse 中包含了 Result 字段。
message SearchResponse { |
引入定义
使用其他 .proto 文件中的消息定义。import "myproject/other_protos.proto";
嵌套类型
层数没有限制,
message SearchResponse { |
引用嵌套类型
message SomeOtherMessage { |
更新消息类型
Any
可以让你使用消息时作为内嵌类型,不需要定义.proto文件。
包括一个任意序列化消息类型是 bytes,还有一个 URL 作为全局标识符。默认 type.googleapis.com/packagename.messagename
使用 Any 类型,需要引入 import google/protobuf/any.proto
import "google/protobuf/any.proto"; |
Packages
可以在 .proto 文件中增加一个可选的 package 限定符,用来防止协议消息类型间的命名冲突
package foo.bar; |
在定义消息字段时使用
message Foo { |
定义 RPC 服务
定义 RPC 服务。pb编译器会生成服务接口代码。gRPC就是使用pb来实现的。跨语言,跨平台的开源RPC系统。
service SearchService { |
JSON 映射
proto3 支持编码为JSON,
有个对应类型列表,查看原文