亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

pb- 使用

系統 2758 0

8.?更新Message類型

如果現有message類型不能在滿足業務需求,例如,需要新增一個字段,但是我們卻希望依然能夠使用原來的.proto生成的代碼。完全沒有問題,僅需記住如下規則:

  1. 千萬不要修改現有字段后邊的數值標簽
  2. 只能新增optional或者repeated字段
  3. 可以刪除非必須字段,但是他們的數字標簽不能再被使用。最好的方法是不刪除,而是修改名字,比如在前綴上加OBSOLETE_,這樣就可以避免后人盡量少的出錯。
  4. 非required字段可以轉化成extension字段,反之亦然,同時保留原類型和數字標簽
  5. int32, uint32, int64, uint64, 和bool是兼容的。即這些字段可以相互切換,在代碼處理的時候,不會出錯,但是小心范圍小的數據接收范圍大的數據會發生截斷
  6. sint32, sint64是相互兼容的,但是不與其他整型類型兼容
  7. string和bytes是兼容的,因為bytes也是合法的UTF-8
  8. Embedded messages are compatible with bytes if the bytes contain an encoded version of the message(不知道怎么翻譯了)
  9. fixed32與 sfixed32兼容, fixed64 與sfixed64兼容
  10. optional與repeated兼容,也存在數據截斷,假如講一個repeated的序列化后的數據作為輸入給客戶端,客戶端會截取最后一個原子類型的字節。或者,如果是一個message類型的字段的話,合并所有的元素。
  11. 可以修改字段默認值

?

?

?

?

?

?

原創作品,允許轉載,轉載時請務必以超鏈接形式標明文章? 原始出處 ?、作者信息 石頭兒 本聲明 。否則將追究法律責任。http://shitouer.cn/2013/04/google-protocol-buffers-tutorial/

1. 概述

前兩篇文章,我們概括介紹《 Google Protocol Buffers 概述 》以及帶領大家簡單的《 Google Protocol Buffers 入門 》,接下來,再稍微詳細一點介紹Protocol Buffers書寫語言。該篇文章主要講解如何使用PB語言構建數據,包括.proto文件語法及如果使用.proto文件生成數據存取類。

本篇主要包括:

  • 定義一個PB message類型
  • 介紹PB 數據類型
  • Optional字段及其默認值
  • 枚舉類型
  • 使用其他Message類型作為filed類型
  • 嵌套類型
  • 更新Message

2.?定義一個PB message類型

假如現在需要定義搜索請求的message格式,每條message包含三個字段:搜索語句(query string),需要的返回結果頁數(page_number),以及該頁上的結果數。可如下定義.proto文件。

    message SearchRequest {

  required string query = 1;

  optional int32 page_number = 2;

  optional int32 result_per_page = 3;

}
  

該message定義聲明三個字段(name/value pairs),每個字段有一個名字和類型。

?2.1 聲明字段類型

上例中,所有的字段類型均為標準類型:兩個整型和一個字符串類型。當然,也可以指定復合類型:枚舉類型和其他自定義message類型。

2.2 給字段賦值數字標簽

從上例中可以發現,message中定義的每個字段都有一個唯一的數字標簽。該標簽的作用是在二進制message中唯一標示該字段,一旦定義該字段的值就不能夠再更改。有一點需要強調:1~15的數字標簽編碼后僅占一個字節(byte),包括數字標簽和字段類型。16~2047的數字標簽占兩個字節(byte)。因此,1~15的數字標簽應該用于最頻繁出現的元素。設計時要考慮到不要一次用完1~15的標簽,要考慮到將來也可能出現頻繁出現的元素。

最小的數字標簽是1,最大的數字標簽是2的29次方-1,也即?536,870,911。但是并不是這之間所有的數字標簽你都能用,例如19000~19999。這個區間的數字標簽就像是java中的保留字一樣,他們是PB的保留數字標簽。如果該區間的數字標簽出現在.proto文件中,PB編譯器會出錯。

2.3 字段標示符

字段標示符有三個:

message的沒一個字段,都要用如下的三個修飾符(modifier)來聲明:

  1. required:必須賦值,不能為空,否則該條message會被認為是“uninitialized”。build一個“uninitialized” message會拋出一個RuntimeException異常,解析一條“uninitialized” message會拋出一條IOException異常。除此之外,“required”字段跟“optional”字段并無差別。
  2. optional:字段可以賦值,也可以不賦值。假如沒有賦值的話,會被賦上默認值。對于簡單類型,默認值可以自己設定,例如上例的PhoneNumber中的PhoneType字段。如果沒有自行設定,會被賦上一個系統默認值,數字類型會被賦為0,String類型會被賦為空字符串,bool類型會被賦為false。對于內置的message,默認值為該message的默認實例或者原型,即其內所有字段均為設置。當獲取沒有顯式設置值的optional字段的值時,就會返回該字段的默認值。
  3. repeated:該字段可以重復任意次數,包括0次。重復數據的順序將會保存在protocol buffer中,將這個字段想象成一個可以自動設置size的數組就可以了。

由于一些歷史原因,數字類型的repeated字段性能有些不盡人意,但是,PB已經做了改進,但是需要再添加一點改動,即在聲明后添加[packed=true]例如:

    repeated int32 samples = 4 [packed=true];
  

Notice :應該格外小心定義Required字段。當因為某原因要把Required字段改為Optional字段是,會有問題,老版本讀取器會認為消息中沒有該字段不完整,可能會拒絕或者丟棄該字段(Google文檔是這么說的,但是我試了一下,將required的改為optional的,再用原來required時候的解析代碼去讀,如果字段賦值的話,并不會出錯,但是如果字段未賦值,會報這樣錯誤:Exception in thread “main” com.google.protobuf.InvalidProtocolBufferException: Message missing required fields:fieldname)。在設計時,盡量將這種驗證放在應用程序端的完成。Google的一些工程師對此也很困惑,他們覺得,required類型壞處大于好處,應該盡量僅適用optional或者repeated的。但也并不是所有的人都這么想。

2.4 同一.proto文件定義多個message

PB支持同一.proto文件定義多個message。這在需要定義相關message的時候非常有用,例如:除了搜索請求message,還需要定義搜索響應message,可以再同一.proto文件中定義:

    message SearchRequest {



required string query = 1;



optional int32 page_number = 2;



optional int32 result_per_page = 3;



}



message SearchResponse {



...



}
  

2.5 添加評論

使用C/C++風格的注釋 // syntax,如下例子:

    message SearchRequest {



required string query = 1;



optional int32 page_number = 2;// Which page number do we want?



optional int32 result_per_page = 3;// Number of results to return per page.



}
  

2.6 編譯.proto文件后產生了什么?

用PB 編譯器運行.proto文件后,會按照定義的格式,生成指定語言的一系列代買,這些代碼的功能包括:字段值的getter,setter,序列化message并寫入到輸出流,從輸入流接寫成message等。

對于Java,編譯器生成一個.java文件,該java文件內包含幾個內部類,分別對應.proto文件中定義的message 類型,以及將來用于創建message類實例的Builder類。

3. 標準值類型

.proto Type Notes C++ Type Java Type Python Type [2]
double ? double double float
float ? float float float
int32 使用可變長編碼. 對于負數比較低效,如果負數較多,請使用sint32 int32 int int
int64 使用可變長編碼. 對于負數比較低效,如果負數較多,請使用sint64 int64 long int/long
uint32 使用可變長編碼 uint32 int
int/long
uint64 使用可變長編碼 uint64 long
int/long
sint32 使用可變長編碼.?Signed int value. 編碼負數比int32更高效 int32 int int
sint64 使用可變長編碼.?Signed int value. 編碼負數比int64更高效 int64 long int/long
fixed32 恒定四個字節。如果數值幾乎總是大于2的28次方,該類型比unit32更高效。 uint32 int
int
fixed64 恒定四個字節。如果數值幾乎總是大于2的56次方,該類型比unit64更高效。 uint64 long
int/long
sfixed32 恒定四個字節 int32 int int
sfixed64 恒定八個字節 int64 long int/long
bool ? bool boolean boolean
string A string must always contain UTF-8 encoded or 7-bit ASCII text. string String str/unicode
bytes 包含任意數量順序的字節 string ByteString str

4.?Optional字段及其默認值

上面提到,PB允許設置可選字段(optional)。顧名思義,在一條message中,該字段可設值也可不設。假如沒有設置,那么在解析該字段的時候,會根據該字段類型,給其賦一個類型默認值。除此之外,也可以在定義message格式的時候,就為optional字段設置一個默認值,如下:

    optional int32 result_per_page = 3 [default = 10];
  

假如沒有賦值的話,會被賦上默認值。對于簡單類型,默認值可以自己設定,例如上例的PhoneNumber中的PhoneType字段。如果沒有自行設定,會被賦上一個系統默認值,數字類型會被賦為0,String類型會被賦為空字符串,bool類型會被賦為false。對于枚舉類型,默認值是枚舉列表中第一個值。

5. 枚舉類型

在定義message類型的時候,也許會有這樣一種需求:其中的一個字段僅需要包含預定義的若干個值即可。比如,對于每一個搜索請求,現需要增加一個分類字段,分類包含:UNIVERSAL, WEB, IMAGES, LOCAL, NEWS, PRODUCTS or VIDEO。要實現該功能,僅需要增加一個枚舉類型字段。如下:

    message SearchRequest {

    required string query = 1;

    optional int32 page_number = 2;

    optional int32 result_per_page = 3 [default = 10];

    enum Corpus {

       UNIVERSAL = 0;

       WEB = 1;

       IMAGES = 2;

       LOCAL = 3;

       NEWS = 4;

       PRODUCTS = 5;

       VIDEO = 6;

    }

    optional Corpus corpus = 4 [default = UNIVERSAL];

}
  

還可以給枚舉值設置別名,僅需將相同的數字標簽設置給不同的名稱即可。這里,必須得設置allow_alias為true,否則PB編譯器會報錯。

    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.

}
  

可以定義枚舉在一個message內部,如上例。也可以定義在message的外部,這樣的枚舉可以被其他任何.proto文件內的message復用。

6.?使用其他Message類型作為filed類型

PB允許使用message類型作為filed類型。例如,在搜索相應message中,包含一個結果message。此時,只需要定義一個結果message,然后再.proto文件中,在搜索結果message中新增一個字段,該字段的類型設置為結果message即可。如下:

    message SearchResponse {

    repeated Result result = 1;

}



message Result {

    required string url = 1;

    optional string title = 2;

    repeated string snippets = 3;

}
  

6.1 導入定義

在上例中,Result message類型與SearchResponse 定義在同一個文件中,假如有這么一種情況,這里所要使用的Resultmessage已經在其他的.proto文件中定義了呢?

可以通過導入其他.proto文件來使用其內的定義。為達此目的,需要在現.proto文件前增加一條import語句:

    import "myproject/other_protos.proto";
  

7. 嵌套類型

PB支持message內嵌套message,如下例子中,Result message 定義在了SearchResponse內:

    message SearchResponse {

  message Result {

    required string url = 1;

    optional string title = 2;

    repeated string snippets = 3;

  }

  repeated Result result = 1;

}
  

如果想要在父Message外復用該message的話,可以用Parent.Type格式來引用。

    message SomeOtherMessage {

  optional SearchResponse.Result result = 1;

}
  

PB支持無限深層次的message嵌套:

    message Outer {                  // Level 0

  message MiddleAA {  // Level 1

    message Inner {   // Level 2

      required int64 ival = 1;

      optional bool  booly = 2;

    }

  }

  message MiddleBB {  // Level 1

    message Inner {   // Level 2

      required int32 ival = 1;

      optional bool  booly = 2;

    }

  }

}
  

8.?更新Message類型

如果現有message類型不能在滿足業務需求,例如,需要新增一個字段,但是我們卻希望依然能夠使用原來的.proto生成的代碼。完全沒有問題,僅需記住如下規則:

  1. 千萬不要修改現有字段后邊的數值標簽
  2. 只能新增optional或者repeated字段
  3. 可以刪除非必須字段,但是他們的數字標簽不能再被使用。最好的方法是不刪除,而是修改名字,比如在前綴上加OBSOLETE_,這樣就可以避免后人盡量少的出錯。
  4. 非required字段可以轉化成extension字段,反之亦然,同時保留原類型和數字標簽
  5. int32, uint32, int64, uint64, 和bool是兼容的。即這些字段可以相互切換,在代碼處理的時候,不會出錯,但是小心范圍小的數據接收范圍大的數據會發生截斷
  6. sint32, sint64是相互兼容的,但是不與其他整型類型兼容
  7. string和bytes是兼容的,因為bytes也是合法的UTF-8
  8. Embedded messages are compatible with bytes if the bytes contain an encoded version of the message(不知道怎么翻譯了)
  9. fixed32與 sfixed32兼容, fixed64 與sfixed64兼容
  10. optional與repeated兼容,也存在數據截斷,假如講一個repeated的序列化后的數據作為輸入給客戶端,客戶端會截取最后一個原子類型的字節。或者,如果是一個message類型的字段的話,合并所有的元素。
  11. 可以修改字段默認值

?9. Package

PB建議在.proto文件開頭添加一個package說明符來避免不同message類型的名字沖突:

    package foo.bar;



message Open { ... }
  

這樣,就可以使用該package標示符來定義該message類型的字段:

    message Foo {



    ...



    required foo.bar.Open open = 1;



    ...



}
  

不同語言,因為添加package標示符,生成的代碼也會有所不同,Java中,該package將會被用作java文件的package。如果不想這樣的話,也可在.proto文件中顯式指明package,該字段是:java_package。

譯自:https://developers.google.com/protocol-buffers/docs/proto

推薦閱讀順序,希望給你帶來收獲~

Google Protocol Buffers 概述

Google Protocol Buffers 入門

Protocol Buffers 語法指南

Google Protocol Buffers 編碼(Encoding)

http://shitouer.cn/2013/04/protocol-buffers-language-guide/

?

pb- 使用


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 午夜宅男在线观看 | 91精品国产欧美一区二区 | 日本国产成人精品视频 | 欧美一区二区三区在观看 | 韩毛片 | 天天操天天干天天做 | 国产福利一区二区在线观看 | 亚洲图片欧美 | 91精品国产免费久久国语麻豆 | 久久国产精品久久精 | 欧美激情久久欧美激情 | 日韩中文字幕在线视频 | 日韩不卡一区二区三区 | 亚洲日本视频在线观看 | 精品国产一区二区三区四 | 国产亚洲欧洲精品 | 亚洲国产精品久久婷婷 | 国产精品伦理一二三区伦理 | 国产一区二区在线观看免费 | 九九99re在线视频精品免费 | 久久成人免费观看草草影院 | 中文字幕国产专区 | 国产一级特黄特色aa毛片 | 日本午夜www高清视频 | 日本免费特黄aa毛片 | 伊人99热| 激情四房| 日日摸夜夜摸狠狠摸97 | 日本视频久久 | 国产在线一区二区 | 久久精品无码一区二区三区 | 色就色综合| 99视频在线观看免费视频 | 久久一区二区三区不卡 | 免费看一级欧美毛片 | 手机看片日韩日韩国产在线看 | 91爱爱视频| 久草免费新视频 | 青青青爽线在线视频观看 | 久久ri精品高清一区二区三区 | 日韩成人三级 |