默认值
解析消息时, 如果被编码的消息没有包含一个特定的元素, 被解析的对象对应的字段被设置为默认值. 默认值是和类型有关的:
- 对于strings, 默认值是空字符串(注, 是"", 而不是null)
- 对于bytes, 默认值是空字节(注, 应该是byte[0], 注意这里也不是null)
- 对于bool, 默认值是false.
- 对于数字类型, 默认值是0.
- 对于枚举, 默认值是第一个定义的枚举值, 而这个值必须是0.
- 对于消息字段, 默认值和语言相关,参考generated code guide
- 对于重复字段, 默认值是空(通常都是空列表)
注意: 对于基本的消息字段, 当消息被解析后, 是不知道该值是默认值还是刚好设置了和默认值相同的值(例如一个bool设置为false,当你不希望这个bool变量能控制程序的默认行为,不要用一个bool值然后当设置为false时来切换某些行为。同样请注意: 如果一个简单消息字段被设置为它的默认值, 这个值不会被序列化.
枚举
简单示例
在下面的例子中, 服务消息中添加一个名为Corpus的枚举类型, 定义好所有可能的值, 然后添加一个类型为Corpus的字段:
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的常量作为它的第一个元素. 这是因为:
- 默认值:必须有一个0值, 这样我们才能用0来作为数值默认值.
- 兼容性:0值必须是第一个元素, 兼容proto2语法,在proto2中默认值总是第一个枚举值
别名设置
可以通过将相同值赋值给不同的枚举常量来定义别名。需要设置allow_alias选项为true, 否则当发现别名时protocol编译器会报错。
enum EnumAllowingAlias {
option allow_alias = true;
UNKNOWN = 0;
STARTED = 1;
RUNNING = 1;
}
enum EnumNotAllowingAlias {
UNKNOWN = 0;
STARTED = 1;
// RUNNING = 1; // Uncommenting this line will cause a compile error inside Google and a warning message outside.
}
注意事项
枚举常量必须在32位整形的范围内,由于枚举值使用varint encoding,如果设置为负值,效率比较低不推荐使用。你可以在消息定义中定义枚举, 如前面例子, 或者在外部 - 这些枚举可以在.proto文件的任意消息定义中复用。在一个消息中声明的枚举类型作为别的消息的字段类型, 需要使用语法MessageType.EnumType.
保留字段
当你在某次更新消息中屏蔽或者删除了一个字段的话,未来的使用着可能在他们的更新中重用这个标签数字来标记他们自己的字段。然后当他们加载旧的消息的时候就会出现很多问题,包括数据冲突,隐藏的bug等等。指定这个字段的标签数字(或者名字,名字可能在序列化为JSON的时候可能冲突)标记为reserved来保证他们不会再次被使用。如果以后的人试用的话protobuf编译器会提示出错。
enum Foo {
reserved 2, 15, 9 to 11, 40 to max;
reserved "FOO", "BAR";
}
注意一个reserved字段不能既有标签数字又有名字。
注意:生成的枚举类型数量代码可能会受到语言限制(一般低于1000,具体参考语言类型限制)