protoc go插件編寫之三 (自定義選項(xiàng))

選項(xiàng) [options]

.proto文件中的各個(gè)聲明【message呀撩扒,service呀等等】可以使用許多選項(xiàng)進(jìn)行注釋闯袒。選項(xiàng)不會改變聲明的整體含義历帚,但可能會影響在特定上下文中處理聲明的方式沽甥。

可用選項(xiàng)的完整列表在google/protobuf/descriptor.proto中定義。

一些選項(xiàng)是文件級別的驻仅, 只能在頂級內(nèi)容區(qū)谅畅, 而不能在任何 message, 或enum噪服,或service中定義毡泻。一些是消息級別的, 只能定義在message內(nèi)粘优, 一些是字段級別的仇味,只能定義在filed內(nèi)。選項(xiàng)也可以寫在枚舉類型雹顺,枚舉值丹墨,字段,服務(wù)類型和服務(wù)方法中嬉愧;但是贩挣,目前尚無任何針對這些選項(xiàng)的有用選項(xiàng)。

  • file level options

    • 例1: go_package 定義了go中英染,包的導(dǎo)入路徑(其包引用此包的路徑揽惹,功能和 命令中的-M類似,但是優(yōu)先級低于-M參數(shù))四康;
    options go_package = github.com/kekek/test; 
    
    • 例2: optimize_for, 可以設(shè)置為 SPEED, CODE_SIZE, 或 LITE_RUNTIME狭握, 只對C++ 或者java起作用
    option optimize_for = CODE_SIZE;
    
  • message level options

    例1:message_set_wire_format, 如果設(shè)置為true闪金,則消息使用另一種二進(jìn)制格式,旨在與Google內(nèi)部使用的舊格式MessageSet兼容论颅。 Google外部的用戶可能永遠(yuǎn)不需要使用此選項(xiàng)哎垦。

    message Foo {
        option message_set_wire_format = true;
        extensions 4 to max;
    }
    
    
  • filed options

    例1: packed, 如果在基本數(shù)字類型的重復(fù)字段上設(shè)置為true,則使用更緊湊的編碼恃疯。使用此選項(xiàng)沒有任何弊端漏设。但是,請注意今妄,在版本2.3.0之前郑口,解析器在不期望收到打包數(shù)據(jù)時(shí)將忽略該數(shù)據(jù)鸳碧。因此,不可能在不破壞電線兼容性的情況下將現(xiàn)有字段更改為打包格式犬性。在2.3.0及更高版本中瞻离,此更改是安全的,因?yàn)榭纱虬侄蔚慕馕銎鲗⑹冀K接受兩種格式乒裆,但是如果必須使用舊的protobuf版本處理舊程序套利,請務(wù)必小心。

    repeated int32 samples = 4 [packed=true];
    

    例2: deprecated, 如果設(shè)置為true鹤耍,則表明該字段已棄用肉迫,并且不應(yīng)由新代碼使用。在大多數(shù)語言中稿黄,這沒有實(shí)際效果喊衫。在Java中,這成為@Deprecated批注抛猖。

    optional int32 old_field = 6 [deprecated=true];
    

自定義選項(xiàng) [Custom Options]

Protocol Buffers 允許自定義選項(xiàng)格侯,這是大多數(shù)人用不到的功能, 且自定義選項(xiàng)僅支持proto3财著。

由于"選項(xiàng)" 是由 google/protobuf/descriptor.proto中定義的消息定義的(例如FileOptions或FieldOptions)联四,因此自定義選項(xiàng)僅是擴(kuò)展這些消息而已。

例如:

import "google/protobuf/descriptor.proto";

extend google.protobuf.MessageOptions {
  optional string my_option = 51234;
}

message MyMessage {
  option (my_option) = "Hello world!";
}

在這里撑教,我們通過擴(kuò)展MessageOptions定義了一個(gè)新的消息級選項(xiàng)朝墩。當(dāng)我們使用選項(xiàng)時(shí),選項(xiàng)名稱必須用括號括起來以表明它是擴(kuò)展名伟姐。我們現(xiàn)在可以像這樣在C++中讀取my_option的值:


string value = MyMessage::descriptor()->options().GetExtension(my_option);

在這里收苏,MyMessage :: descriptor()-> options()返回MyMessage的MessageOptions協(xié)議消息。從中讀取自定義選項(xiàng)就像讀取任何其他擴(kuò)展名一樣愤兵。

在protobuf protocol 中鹿霸,可以為每種構(gòu)造定義自定義選項(xiàng)。這是使用各種選項(xiàng)的示例:

import "google/protobuf/descriptor.proto";

extend google.protobuf.FileOptions {
  optional string my_file_option = 50000;
}
extend google.protobuf.MessageOptions {
  optional int32 my_message_option = 50001;
}
extend google.protobuf.FieldOptions {
  optional float my_field_option = 50002;
}
extend google.protobuf.OneofOptions {
  optional int64 my_oneof_option = 50003;
}
extend google.protobuf.EnumOptions {
  optional bool my_enum_option = 50004;
}
extend google.protobuf.EnumValueOptions {
  optional uint32 my_enum_value_option = 50005;
}
extend google.protobuf.ServiceOptions {
  optional MyEnum my_service_option = 50006;
}
extend google.protobuf.MethodOptions {
  optional MyMessage my_method_option = 50007;
}

option (my_file_option) = "Hello world!";

message MyMessage {
  option (my_message_option) = 1234;

  optional int32 foo = 1 [(my_field_option) = 4.5];
  optional string bar = 2;
  oneof qux {
    option (my_oneof_option) = 42;

    string quux = 3;
  }
}

enum MyEnum {
  option (my_enum_option) = true;

  FOO = 1 [(my_enum_value_option) = 321];
  BAR = 2;
}

message RequestType {}
message ResponseType {}

service MyService {
  option (my_service_option) = FOO;

  rpc MyMethod(RequestType) returns(ResponseType) {
    // Note:  my_method_option has type MyMessage.  We can set each field
    //   within it using a separate "option" line.
    option (my_method_option).foo = 567;
    option (my_method_option).bar = "Some string";
  }
}


請注意秆乳,如果要在自定義選項(xiàng)之外的其他程序包中使用自定義選項(xiàng)懦鼠,則必須在選項(xiàng)名稱前加上程序包名稱,就像鍵入類型名稱一樣屹堰。例如:

  • foo.proto
import "google/protobuf/descriptor.proto";
package foo;
extend google.protobuf.MessageOptions {
  optional string my_option = 51234;
}
  • bar.proto
import "foo.proto";
package bar;
message MyMessage {
  option (foo.my_option) = "Hello world!";
}

最后一件事:由于自定義選項(xiàng)是擴(kuò)展名肛冶,因此必須像其他任何字段或擴(kuò)展名一樣為它們分配字段編號。在上面的示例中扯键,我們使用了范圍為50000-99999的字段號睦袖。此范圍保留供各個(gè)組織內(nèi)部使用,因此您可以在內(nèi)部應(yīng)用程序中自由使用此范圍內(nèi)的數(shù)字荣刑。但是馅笙,如果您打算在公共應(yīng)用程序中使用自定義選項(xiàng)伦乔,那么確保您的字段編號在全球范圍內(nèi)是唯一的,這一點(diǎn)很重要延蟹。要獲取全局唯一的字段號评矩,請發(fā)送請求以將條目添加到protobuf全局?jǐn)U展注冊表中。通常阱飘,您只需要一個(gè)分機(jī)號碼斥杜。您可以通過將多個(gè)選項(xiàng)放在一個(gè)子消息中來聲明多個(gè)僅具有一個(gè)分機(jī)號的選項(xiàng):

message FooOptions {
  optional int32 opt1 = 1;
  optional string opt2 = 2;
}

extend google.protobuf.FieldOptions {
  optional FooOptions foo_options = 1234;
}

// usage:
message Bar {
  optional int32 a = 1 [(foo_options).opt1 = 123, (foo_options).opt2 = "baz"];
  // alternative aggregate syntax (uses TextFormat):
  optional int32 b = 2 [(foo_options) = { opt1: 123 opt2: "baz" }];
}

另外,請注意沥匈,每個(gè)選項(xiàng)類型(文件級蔗喂,消息級,字段級等)都有自己的數(shù)字空間高帖,例如您可以使用相同的編號聲明FieldOptions和MessageOptions的擴(kuò)展名缰儿。

參考文獻(xiàn):

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市散址,隨后出現(xiàn)的幾起案子乖阵,更是在濱河造成了極大的恐慌,老刑警劉巖预麸,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瞪浸,死亡現(xiàn)場離奇詭異,居然都是意外死亡吏祸,警方通過查閱死者的電腦和手機(jī)对蒲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贡翘,“玉大人蹈矮,你說我怎么就攤上這事∶” “怎么了泛鸟?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長踊东。 經(jīng)常有香客問我谈况,道長,這世上最難降的妖魔是什么递胧? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮赡茸,結(jié)果婚禮上缎脾,老公的妹妹穿的比我還像新娘。我一直安慰自己占卧,他們只是感情好遗菠,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布联喘。 她就那樣靜靜地躺著,像睡著了一般辙纬。 火紅的嫁衣襯著肌膚如雪豁遭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天贺拣,我揣著相機(jī)與錄音蓖谢,去河邊找鬼。 笑死譬涡,一個(gè)胖子當(dāng)著我的面吹牛闪幽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播涡匀,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼盯腌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了陨瘩?” 一聲冷哼從身側(cè)響起腕够,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎舌劳,沒想到半個(gè)月后帚湘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蒿囤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年客们,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片材诽。...
    茶點(diǎn)故事閱讀 40,680評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡底挫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出脸侥,到底是詐尸還是另有隱情建邓,我是刑警寧澤,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布睁枕,位于F島的核電站官边,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏外遇。R本人自食惡果不足惜注簿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望跳仿。 院中可真熱鬧诡渴,春花似錦、人聲如沸菲语。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至眼耀,卻和暖如春英支,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哮伟。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工干花, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人澈吨。 一個(gè)月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓把敢,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谅辣。 傳聞我的和親對象是個(gè)殘疾皇子修赞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容