枚举

当需要定义一个消息类型的时候,可能想为一个字段指定某“预定义值序列”中的一个值。在message消息定义中添加一个枚举(enum)并且为每个可能的值定义一个常量就可以了。

  1. message NewService {
  2. string msn = 1;
  3. string streamKey = 2;
  4. enum Corpus {
  5. UNIVERSAL = 0;
  6. WEB = 1;
  7. IMAGES = 2;
  8. LOCAL = 3;
  9. NEWS = 4;
  10. PRODUCTS = 5;
  11. VIDEO = 6;
  12. }
  13. Corpus corpus = 4;
  14. }

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 之类的封闭枚举类型的语言中,枚举值会被用来标识未识别的值,并且特殊的访问器可以访问到底层整数。

在其他情况下,如果消息被序列化,则无法识别的值仍将与消息一起序列化。