枚举器常量必须在32位整数范围内。 由于枚举值在导线上使用varint编码,因此负值效率不高,因此不建议使用。 您可以在消息定义内定义枚举,如上例所示,也可以在外部定义-这些枚举可以在.proto文件中的任何消息定义中重复使用。 您还可以使用语法_MessageType . EnumType_将一条消息中声明的枚举类型用作另一条消息中的字段类型。
在使用枚举的.proto上运行协议缓冲区编译器时,生成的代码将具有一个对应的Java或C ++枚举,一个特殊的Python EnumDescriptor类,用于在运行时创建带有整数值的符号常量集 生成的类。
反序列化期间,无法识别的枚举值将保留在消息中,尽管在反序列化消息时如何表示该值取决于语言。 在支持具有超出指定符号范围的值的开放式枚举类型的语言(例如C ++和Go)中,未知的枚举值仅存储为其基础整数表示形式。 在诸如Java之类的具有封闭枚举类型的语言中,枚举中的大小写用于表示无法识别的值,并且可以使用特殊的访问器访问基础整数。 无论哪种情况,如果消息被序列化,则无法识别的值仍将与消息一起序列化。
有关如何在应用程序中使用消息枚举的更多信息,请参见针对所选语言的生成的代码指南。
Reserved Values如果通过完全删除枚举条目或将其注释掉来更新枚举类型,则将来的用户在自己对类型进行更新时可以重用数值。 如果他们以后加载同一.proto的旧版本,可能会导致严重的问题,包括数据损坏,隐私错误等。 确保不会发生这种情况的一种方法是指定保留已删除条目的数值(和/或名称,这也可能导致JSON序列化问题)。 如果将来有任何用户尝试使用这些标识符,则协议缓冲区编译器会抱怨。 您可以使用max关键字指定保留的数值范围达到最大可能值。
enum Foo { reserved 2, 15, 9 to 11, 40 to max; reserved "FOO", "BAR"; }请注意,您不能在同一保留语句中混合使用字段名和数字值。
Using Other Message Types您可以使用其他消息类型作为字段类型。 例如,假设您要在每条SearchResponse消息中包括结果消息–为此,您可以在同一.proto中定义结果消息类型,然后在SearchResponse中指定结果类型的字段:
message SearchResponse { repeated Result results = 1; } message Result { string url = 1; string title = 2; repeated string snippets = 3; } Importing Definitions在上面的示例中,“结果”消息类型与SearchResponse定义在同一文件中-如果要在另一个.proto文件中定义要用作字段类型的消息类型,该怎么办?
您可以通过导入其他.proto文件使用它们的定义。 要导入另一个.proto的定义,请在文件顶部添加一个import语句:
import "myproject/other_protos.proto";默认情况下,您只能使用直接导入的.proto文件中的定义。 但是,有时您可能需要将.proto文件移动到新位置。 现在,您可以直接在原始位置放置一个虚拟.proto文件,而不是直接移动.proto文件并一次更改所有呼叫站点,而是使用import public概念将所有导入转发到新位置。 任何导入包含导入公共声明的原型的人都可以可传递地依赖导入公共依赖项。 例如:
// new.proto // All definitions are moved here // old.proto // This is the proto that all clients are importing. import public "new.proto"; import "other.proto"; // client.proto import "old.proto"; // You use definitions from old.proto and new.proto, but not other.proto协议编译器使用-I /-proto_path标志在协议编译器命令行中指定的一组目录中搜索导入的文件。 如果未给出标志,它将在调用编译器的目录中查找。 通常,应将--proto_path标志设置为项目的根目录,并对所有导入使用完全限定的名称。
Using proto2 Message Types可以导入proto2消息类型并在proto3消息中使用它们,反之亦然。 但是,不能在proto3语法中直接使用proto2枚举(如果导入的proto2消息使用它们,也可以)。
Nested Types您可以在其他消息类型中定义和使用消息类型,如以下示例所示–在SearchResponse消息中定义了Result消息:
message SearchResponse { message Result { string url = 1; string title = 2; repeated string snippets = 3; } repeated Result results = 1; }如果要在其父消息类型之外重用此消息类型,则将其称为_Parent . Type_:
message SomeOtherMessage { SearchResponse.Result result = 1; }