選項(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):