介绍一下消息的不同类型和引用
使用复杂消息类型
您可以使用其他消息类型作为字段类型。例如,假设你想在每个SearchResponse
消息中包含Result
消息,您可以在同一个.proto
中定义一个Result
消息类型,然后在SearchResponse
中指定一个Result
类型的字段:
1 | message SearchResponse { |
引入其他消息文件
在上述示例中,Result
消息类型与SearchResponse
在相同的文件中定义, 如果要使用的消息类型已经在另一个.proto
文件中定义了怎么解决呢?
你可以通过import
引入其他的.proto
文件:
1 | import "myproject/other_protos.proto"; |
注意
接上边的例子,假如a.proto
引入了b.proto
,但是b.proto
更换了位置,路径变成了test/b.proto
(随便举例),我们有两种解决办法:
- 修改
a.proto
中的import
语句,直接import "test/b.proto"
- 在
b.proto
文件原来的位置,创建一个b.proto
文件,文件内容为import public "test/b.proto"
,就可以了
import
对proto2
和proto3
都适用
嵌套类型
您可以在其他消息类型中定义和使用消息类型,如下,Result
消息定义在SearchResponse
消息中:
1 | message SearchResponse { |
如果想重复使用Result
,可以用Parent.Type
的方式使用:
1 | message AnotherResponse { |
修改更新现有的消息格式
修改时要注意的规则:
- 不要改变已经存在字段的标签
- 添加一个字段时,旧的消息将会收到这个字段的默认值
- 删除一个字段时,记得把该字段的标签添加到
reserved
里 - int32,uint32,int64,uint64和bool都是兼容的。这意味着您可以将这些类型之一的字段更改为另一个,而不会破坏前向或后向兼容性。转 大专栏 Protocol Buffers学习(4):更多消息类型换过程相当于C ++中将该数字转换为该类型(例如,如果将64位数字读为int32, 它将被截断到32位)
- sint32和sint64相互兼容,但与其他整数类型不兼容
- 只要字节是有效的UTF-8,字符串和字节是兼容的
- 嵌套消息(message)与包含消息的编码版本的字节(bytes)兼容【表述不清,欢迎大家评论指正】
- fixed32与sfixed32兼容,fixed64与sfixed64兼容
- 枚举兼容int32,uint32,int64和uint64(请注意,如果值不合适,那么值将被截断)。 但是请注意,客户端代码可以在消息反序列化时对它们进行不同的处理:例如,消息中将保留无法识别的proto3枚举类型,但是当消息反序列化时,如何处理和使用的编程语言相关。 Int字段始终保持其值
Any
类型
any类型时谷歌protobuf内置的一个类型,通用类型,使用的时候需要导入google/protbuf/any.proto
1 | import "google/protobuf/any.proto"; |
Oneof
类型
Oneof结构中有多个字段,但是同一时刻只有一个字段生效
定义oneof结构
1 | message SampleMessage { |
oneof中可以是任意类型,除了repeated 字段
生成代码之后,也会对oneof字段生成getter,setter方法,但是出来的值需要你自己判断一下
Maps 类型
如果你要定义一个map,protobuf提供了一个语法:
1 | map<key_type, value_type> map_field = N; |
例如
1 | map<string, Project> projects = 3; |
注意事项
- Map字段不能是
repeated
- Map中的集合是无序的
.proto
文件生成时,map按key排序- 解析或者合并时,后边的会覆盖前边的
packages语法
你可以添加一个可选标识package
到.proto
文件中。用来防止命名冲突
1 | package foo.bar; |
在使用这条消息的时候需要加上package
名字
1 | message Foo { |