五.Protobuf3 枚舉


Protobuf3 枚舉

  定義消息類型時,您可能希望它的一個字段有一個預定義的值列表。例如,假設您希望為每個SearchRequest添加一個corpus字段,其中語料庫可以是UNIVERSAL、WEB、IMAGES、LOCAL、NEWS、PRODUCTS 或VIDEO。您可以非常簡單地通過在消息定義中添加枚舉來實現這一點,每個可能的值都是一個常量。

  在下面的例子中,我們添加了一個名為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作為數值默認值。

  零值必須為第一個元素,以便與proto 2語義兼容,其中第一個枚舉值總是默認的。

  可以通過為不同的枚舉常量分配相同的值來定義別名。為此,您需要將allow_alias選項設置為true,否則協議編譯器會在找到別名時生成錯誤消息。

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位整數的范圍內。由於enum值在傳輸中使用不同的編碼,負值效率低下,因此不推薦使用。您可以在消息定義中定義枚舉,如上例所示,也可以在消息定義之外定義枚舉——這些枚舉可以在 .proto文件中的消息定義中重用。您也可以使用語法MessageType.EnumType,將一條消息中聲明的枚舉類型用作另一條消息中字段的類型

  當你在.proto文件上使用枚舉運行協議緩沖區編譯器時,生成的代碼將具有Java或c++的相應枚舉,Python使用一個EnumDescriptor類,用於在運行時生成的類中創建一組具有整數值的符號常量。

  在反序列化期間,無法識別的枚舉值將保留在消息中,盡管反序列化消息時如何表示這些值取決於編程語言。在支持數值超出指定符號范圍的開放式枚舉類型的語言中,例如c++和Go,未知的枚舉值簡單地存儲為其底層整數表示。在具有封閉枚舉類型的語言(如Java)中,在枚舉中無法識別的值可以用特殊的訪問器訪問。在任一種情況下,如果消息被序列化,則無法識別的值仍將與消息一起序列化。

  有關如何在應用程序中使用消息枚舉的詳細信息,請參閱為您選擇的語言生成的代碼指南。

保留值

  如果通過完全刪除枚舉條目或注釋來更新枚舉類型,將來的用戶可以在對該類型進行自己的更新時重用數值。如果他們以后加載舊版本的相同 .proto內容,這可能會導致嚴重的問題。包括數據損壞、隱私漏洞等。確保不會發生這種情況的一種方法是指定保留已刪除條目的數值(and/or名稱,這也會導致JSON序列化問題)。如果將來有任何用戶試圖使用這些標識符,協議緩沖區編譯器會報錯。您可以使用max關鍵字指定保留的數值范圍達到可能的最大值。

enum Foo {
  reserved 2, 15, 9 to 11, 40 to max;
  reserved "FOO", "BAR";
}

  請注意,不能在同一保留語句中混合字段名和數值。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM