枚举
当需要定义一个消息类型的时候,可能想为一个字段指定某“预定义值序列”中的一个值。在message消息定义中添加一个枚举(enum)并且为每个可能的值定义一个常量就可以了。
message NewService {
string msn = 1;
string streamKey = 2;
enum Corpus {
UNIVERSAL = 0;
WEB = 1;
IMAGES = 2;
LOCAL = 3;
NEWS = 4;
PRODUCTS = 5;
VIDEO = 6;
}
Corpus corpus = 4;
}
Corpus枚举的第一个常量映射为0:每个枚举类型必须将其第一个类型映射为0,这是因为:
- 枚举为 0 的是作为零值,当不赋值的时候,就会是零值。
- 这个零值必须为第一个元素,为了兼容proto2语义,枚举类的第一个值总是默认值.
枚举常量必须在32位整型值的范围内。因为enum值是使用可变编码方式的,对负数不够高效,因此不推荐在enum中使用负数。如上例所示,可以在 一个消息定义的内部或外部定义枚举——这些枚举可以在.proto文件中的任何消息定义里重用。当然也可以在一个消息中声明一个枚举类型,而在另一个不同 的消息中使用它——采用MessageType.EnumType的语法格式。
当对一个使用了枚举的.proto文件运行protocol buffer编译器的时候,生成的代码中将有一个对应的enum(对Java或C++来说),或者一个特殊的EnumDescriptor类(对 Python来说),它被用来在运行时生成的类中创建一系列的整型值符号常量(symbolic constants)。
除此之外在反序列化的过程中,无法被识别的枚举值,将会被保留在 messaage消息中。因为消息反序列化时如何表示是依赖于语言的。在支持指定符号范围之外的值的开放枚举类型的语言中,例如 C++ 和 Go,未知的枚举值只是存储为其基础整数表示。在诸如 Java 之类的封闭枚举类型的语言中,枚举值会被用来标识未识别的值,并且特殊的访问器可以访问到底层整数。
在其他情况下,如果消息被序列化,则无法识别的值仍将与消息一起序列化。