日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

protocol buffer 使用之 .proto 定义规则

發(fā)布時(shí)間:2024/1/18 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 protocol buffer 使用之 .proto 定义规则 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
message為主要關(guān)鍵字,類(lèi)似于java中的class。 定義簡(jiǎn)單的message類(lèi)型: SearchRequest.proto定義了每個(gè)查詢(xún)請(qǐng)求的消息格式,每個(gè)請(qǐng)求都會(huì)有查詢(xún)關(guān)鍵詞query,查詢(xún)結(jié)果的頁(yè)數(shù),每頁(yè)的結(jié)果數(shù)量這三個(gè)屬性。于是 message?SearchRequest{
????????required?string?query?=?1;
????????optional?int32?page_number?=?2;
????????optional?int32?result_per_page?=3;
????????repeated?int32?samples?=?4?[packed= true];????
} message定義了三個(gè)field,每個(gè)field由名字和類(lèi)型來(lái)組成。
  • 指定field類(lèi)型
在這個(gè)例子中,SearchRequest的field都是基本類(lèi)型,兩個(gè)integer(page_number和result_per_page)和一個(gè)Stirng(query),也可以指定復(fù)雜的類(lèi)型屬性,包括枚舉和其它類(lèi)型。
  • 分配標(biāo)簽
每個(gè)field都是唯一數(shù)字的標(biāo)記,這是用來(lái)標(biāo)記這個(gè)field在message二進(jìn)制格式中的位置的,一旦使用就不能再修改順序了。 注:標(biāo)記從1-15只有一個(gè)字節(jié)編碼,包括自增長(zhǎng)屬性(更多的見(jiàn)Protocol Buffer Encoding) 標(biāo)記從16-2047占用兩個(gè)字節(jié)。因此盡量頻繁使用1-15,記住為未來(lái)的擴(kuò)展留下一些位置。 最小的tag你可以定義為1,最大2的29次方-1 ?536870922.你同樣不能使用19000-19999(這個(gè)位置已經(jīng)被GPB自己實(shí)現(xiàn)),
  • 指定field規(guī)則
message?SearchRequest{
????????required?string?query?=?1 ;
????????optional?int32?page_number?=?2 ;
????????optional?int32?result_per_page?=3 ;
????????repeated?int32?samples?=?4? [ packed=true ] ; ????
} 由于歷史原因,repeated字段如果是基本數(shù)字類(lèi)型的話(huà),不能有效地編碼?,F(xiàn)在代碼可以使用特殊選項(xiàng)[packed=true]來(lái)得到更有效率的編碼。 注: ?由于required是永遠(yuǎn)的,應(yīng)該非常慎重地給message某個(gè)字段設(shè)置為required。如果未來(lái)你希望停止寫(xiě)入或者輸出某個(gè)required字段,那就會(huì)成為問(wèn)題;因?yàn)榕f的reader將以為沒(méi)有這個(gè)字段無(wú)法初始化message,會(huì)丟掉這部分信息。一些來(lái)自google的工程師們指出使用required弊大于利,盡量使用optional和repeated。 這個(gè)觀點(diǎn)并不是通用的。
  • 更多message類(lèi)型
多個(gè)message類(lèi)型能被定義在一個(gè)簡(jiǎn)單的.proto文件中,通常是創(chuàng)建具有關(guān)聯(lián)關(guān)系的message時(shí)候這么作。 message?SearchRequest{
????????required?string?query?=?1 ;
????????optional?int32?page_number?=?2 ;
????????optional?int32?result_per_page?=3 ;
????????repeated?int32?samples?=?4? [ packed=true ] ; ????
}
  • 添加注釋
使用c/C++ style 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?
????????repeated?int32?samples?=?4?[packed= true];????
}
  • .proto文件自動(dòng)生成代碼
protocol buffer編譯一個(gè)proto文件,生成對(duì)應(yīng)語(yǔ)言的代碼。 大概包括各個(gè)字段的get和set方法,序列化message到輸出流的方法,從輸入流轉(zhuǎn)成message的方法。 C++,為每個(gè)proto生成一個(gè).h和.cc文件 Java,為每個(gè)proto生成一個(gè).java文件 Python,有點(diǎn)不同,生成一個(gè)module
  • 基本屬性 ?
  • optional字段和默認(rèn)值
當(dāng)含有optional字段的message從流轉(zhuǎn)換成對(duì)象的時(shí)候,如果沒(méi)有包含optional字段的數(shù)據(jù),那么對(duì)象的optional字段會(huì)設(shè)置成默認(rèn)值。 默認(rèn)值可以作為message的描述出現(xiàn)。舉個(gè)例子: optional?int32?result_per_page?=?3? [ default?=?10 ] ; 如??? pasting ???果沒(méi)有指定默認(rèn)值的話(huà),string 默認(rèn)為空串,bool 默認(rèn)為false,數(shù)字類(lèi)型默認(rèn)0,枚舉類(lèi)型,默認(rèn)為類(lèi)型定義中的第一個(gè)值,
  • Enumerations
如果字段的屬性值是固定的幾個(gè)值,可以使用枚舉
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?=?WEB];
}
  • 自定義消息類(lèi)型
可以使用message類(lèi)型做字段的屬性,看例子: message?SearchResponse?{
??repeated?Result?result?=?1;
}
message?Result?{
??required? string?url?=?1;
??optional? string?title?=?2;
??repeated? string?snippets?=?3;
}
  • import 定義
上面的例子SearchResponse 與Result在一個(gè).proto文件中。其實(shí)也可以使用另一個(gè).proto文件來(lái)定義字段類(lèi)型。 你可以通過(guò)import來(lái)定義。 import?"myproject/other_protos.proto"; protocol編譯器查找引入文件是通過(guò)編譯器的命令參數(shù) -I/--proto_path 如果沒(méi)有指定,就在protoc執(zhí)行目錄下尋找。 The protocol compiler searches for imported files in a set of directories specified on the protocol compiler command line using the -I/--proto_path flag.? If no flag was given, it looks in the directory in which the compiler was invoked.? In general you should set the --proto_path flag to the root of your project and use fully qualified names for all imports.
  • 內(nèi)部類(lèi)
你可以定義和使用內(nèi)部message類(lèi)。 message?SearchResponse?{
??message?Result?{
????required?string?url?=?1;
????optional?string?title?=?2;
????repeated?string?snippets?=?3;
??}
??repeated?Result?result?=?1;
} 如果要引用內(nèi)部類(lèi),則通過(guò)parent.type方式來(lái)調(diào)用 message?SomeOtherMessage?{
??optional?SearchResponse.Result?result?=?1;
} 還可以很深、很深的內(nèi)部類(lèi) 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;
????}
??}
}
  • Groups?
?廢棄的屬性,了解即可,采用內(nèi)部類(lèi)代替。 message?SearchResponse?{
??repeated?group?Result?=?1?{
????required?string?url?=?2;
????optional?string?title?=?3;
????repeated?string?snippets?=?4;
??}
}

Extentions extensions 聲明一個(gè)消息中的一定范圍的field的順序數(shù)字用于進(jìn)行擴(kuò)展。其它人可以在自己的.proto文件中重新定義這些消息field,而不需要去修改原始的.proto文件 message?Foo?{
?? // ?
??extensions?100?to?199;
} 這些說(shuō)明100-199的field是保留的。其它用戶(hù)可以用這些field在他們自己的.proto文件中添加新的fields給Foo。舉例: extend?Foo?{
??optional?int32?bar?=?126;
} 說(shuō)明 Foo有一個(gè)optional的int32類(lèi)型的名稱(chēng)為bar的field ? 當(dāng)Foo的message編碼后,數(shù)據(jù)格式就跟用戶(hù)在Foo中定義一個(gè)新的field完全一樣。但是你在程序中訪(fǎng)問(wèn)extension field的方式與訪(fǎng)問(wèn)正常的屬性略微有點(diǎn)不同。生成的extensions的訪(fǎng)問(wèn)代碼是不同的。舉例:c++中如何set屬性bar的值:
Foo?foo;
foo.SetExtension(bar,15); 同樣,Foo 定義了模板訪(fǎng)問(wèn)器 ?HasExtendsion(),ClearExtension(),GetExtension(),MutableExtension(),AddExtension(). 所有 訪(fǎng)問(wèn) ? ? ??
注: ?extensions能使用任何field類(lèi)型,包括自定義消息類(lèi)型。
  • 內(nèi)嵌的extensions
能聲明extensions在另一個(gè)message中
message?Baz?{
??extend?Foo?{
????optional?int32?bar?=?126 ;
??}
??
} 在這個(gè)例子中, the C++ 代碼訪(fǎng)問(wèn)訪(fǎng)問(wèn)這個(gè)屬性:
Foo?foo;
foo.SetExtension(Baz::bar,?15); 換句話(huà)說(shuō),這么做唯一影響是bar定義在了Baz的范圍之內(nèi)。 注意: 容易混淆的地方 聲明一個(gè)消息內(nèi)部的繼承類(lèi)并不意味著外部類(lèi)和extended類(lèi)有任何關(guān)系。 特別 以上的例子并不意味著B(niǎo)az是任何Foo的子類(lèi)。這些只是意味著符號(hào)bar是聲明在Baz的范圍之內(nèi)的, 它看起來(lái)更像是個(gè)靜態(tài)成員。 一個(gè)通用的模式是在extensions的field范圍內(nèi)來(lái)定義extensions,舉例說(shuō)明,這里有一個(gè)Foo的extension作為Baz的一部分的屬性類(lèi)型是Baz
message?Baz?{
??extend?Foo?{
????optional?Baz?foo_ext?=?127 ;
??}
??
} 沒(méi)有必要非得在message內(nèi)部定義一個(gè)extension的類(lèi)型。你也可以這么做:
message?Baz?{
??
}
//?This?can?even?be?in?a?different?file.
extend?Foo?{
??optional?Baz?foo_baz_ext?=?127 ;
} 事實(shí)上,上面的這個(gè)語(yǔ)法更加有效地避免混淆。正如上文所述,內(nèi)部的那種語(yǔ)法語(yǔ)法對(duì)于不是熟悉extensions的人來(lái)說(shuō),經(jīng)常會(huì)錯(cuò)認(rèn)為子類(lèi)。
  • 選擇Extension 順序數(shù)字
非常重要的一點(diǎn)是雙方不能使用同樣數(shù)字添加一樣的message類(lèi)型,這樣extension會(huì)被解釋為錯(cuò)誤類(lèi)型。 可能需要有一個(gè)關(guān)于field的數(shù)字順序的約定來(lái)保證你的project不會(huì)發(fā)生這樣的重復(fù)的問(wèn)題。 如果你的field數(shù)字比較大的話(huà),可以使用max來(lái)指定你的textension范圍上升到最大的范圍 message?Foo?{
??extensions?1000?to?max ;
}
max?is?229?-?1,?or?536,870,911. 19000-19999是protocol buffers的使用的字段,所以這個(gè)范圍內(nèi)的數(shù)字需要區(qū)別開(kāi)來(lái)。 Packages 可以給一個(gè).protol文件增加一個(gè)optional的package描述,來(lái)保證message盡量不會(huì)出現(xiàn)名字相同的重名。 package?foo.bar ;
message?Open?{?
?
} 也可以在指定field類(lèi)型的時(shí)候使用 message?Foo?{
??
??required?foo.bar.Open?open?=?1 ;
??
} package會(huì)根據(jù)選擇的語(yǔ)言來(lái)生成不同的代碼: C++ ? ? ?生成的classes是用C++的namespace來(lái)區(qū)分的。舉例:Open?would?be?in?the?namespace?foo::bar。
Java ? ? ?package用于Java的package,除非你單獨(dú)的指定一個(gè)option?java_package?在.proto文件中。
Python ? package是被忽略的,因?yàn)镻ython的modules是通過(guò)它們的文件位置來(lái)組織的。
  • Packages和name?
在protocol buffer中package名稱(chēng)的方案看起來(lái)像C++,首先,最里面的范圍被搜索,然后搜索次一級(jí)的范圍, 每個(gè)package被認(rèn)為在他的父package內(nèi)。一個(gè). (.foo.bar.Baz)意味著從最外層開(kāi)始. options 在一個(gè)proto文件中,還可以存在一些options。Options不能改變一個(gè)聲明的整體的意義,但是可以影響一定的上下文。 可用的options的完整list定義在 Google/protobuf/descriptor.proto 一些options是第一級(jí)的,意味著它們應(yīng)該被寫(xiě)在頂級(jí)范圍,而不是在任何message,enum,sercie的定義中。 一些options是message級(jí)別的,意味著它們應(yīng)該被寫(xiě)入message的描述中, 一些options是field-level級(jí)別的,意味著它們應(yīng)該被寫(xiě)入field的描述中, options也可以被寫(xiě)入enum類(lèi)型中,enum的值,service類(lèi)型 和service方法; 列舉了常用的options: java_package(file option) 定義生成的java class的package。如果在proto文件中沒(méi)有明確的java_package選項(xiàng),那么默認(rèn)會(huì)使用package關(guān)鍵字指定的package名。 但是proto package通常不會(huì)好于Java packages,因?yàn)閜roto packages通常不會(huì)以domain名稱(chēng)開(kāi)始。 如果不生成java代碼,此選項(xiàng)沒(méi)有任何影響。 option java_package = "com.example.foo"; java_outer_classname:(file option) 指定想要生成的class名稱(chēng),如果此參數(shù)沒(méi)有指定的話(huà),那么默認(rèn)使用.proto文件名來(lái)做為類(lèi)名,并且采用駝峰表示(比如:foo_bar.proto 為 FooBar.java) 如果不生成java代碼,此選項(xiàng)沒(méi)有影響。 option java_outer_classname = "Ponycopter"; optimize_for (file option) 可以設(shè)置為speed、code_size或者lite_runtime. SPEED:默認(rèn)。protocol編譯器會(huì)生成classes代碼,提供了message類(lèi)的序列化、轉(zhuǎn)換和其它通用操作。這個(gè)代碼是被高度優(yōu)化過(guò)的。 CODE_SIZE:?protocol編譯器會(huì)生成最小的classes,并且依賴(lài)共享、基于反射的代碼實(shí)現(xiàn)序列化、轉(zhuǎn)換和其它通用操作。生成的classes代碼小于speed,但是操作會(huì)慢一點(diǎn)。classes會(huì)實(shí)現(xiàn)跟SPEED模式一樣的公共API。這個(gè)模式通常用在一個(gè)應(yīng)用程序包含了大量的proto文件,但是并不需要所有的代碼都執(zhí)行得很快 LITE_RUNTIME:?protocol編譯器會(huì)生成僅僅依賴(lài) lite 運(yùn)行庫(kù)(libprotobuf-lite代替libprotobuf)。lite運(yùn)行時(shí)比全量庫(kù)小很多,省略了某種特性(如: descriptors and reflection)這個(gè)選項(xiàng)對(duì)于運(yùn)行在像移動(dòng)手機(jī)這種有約束平臺(tái)上的應(yīng)用更有效。 編譯器仍然會(huì)對(duì)所有方法生成非常快的代碼實(shí)現(xiàn),就像SPEED模式一樣。protocol編譯器會(huì)用各種語(yǔ)言來(lái)實(shí)現(xiàn)MessageList接口,但是這個(gè)接口僅僅提供了其它模式實(shí)現(xiàn)的Message接口的一部分方法子集。 例子
option?optimize_for? = ?CODE_SIZE ; cc_generic_services, java_generic_services, py_generic_services (file options) 無(wú)論如何,protoc編譯器會(huì)生成基于C++,Java,Python的抽象service代碼,這些默認(rèn)都是true。截至到2.3.0版本,RPC實(shí)現(xiàn)提供了代碼生成插件去生成代碼,不再使用抽象類(lèi)。 //?This?file?relies?on?plugins?to?generate?service?code.
option?cc_generic_services?=?false ;
option?java_generic_services?=?false ;
option?py_generic_services?=?false ; message_set_wire_format (message option) 如果設(shè)置為true,消息使用不同的二進(jìn)制格式來(lái)兼容谷歌內(nèi)部使用的稱(chēng)為MessageSet的舊格式。用戶(hù)在google以外使用,將不再需要使用這個(gè)option。 消息必須按照以下聲明
message?Foo?{
??option?message_set_wire_format?=?true ;
??extensions?4?to?max ;
} packed (field option) 如果設(shè)置為true, 一個(gè)repeated的基本integer類(lèi)型的field,會(huì)使用一種更加緊湊的壓縮編碼。請(qǐng)注意,在2.3.0版之前,protocol生成的解析邏輯收到未預(yù)期的壓縮的數(shù)據(jù)將會(huì)忽略掉。因此,改變一個(gè)已經(jīng)存在的field,一定會(huì)破壞其線(xiàn)性兼容性。在2.3.0以后,這種改變就是安全的,解析邏輯可以識(shí)別壓縮和不壓縮的格式,但是,一定要小心那些使用原先舊版本的protocol的程序。 repeated?int32?samples?=?4? [ packed=true ] ; deprecated (field option): 如果設(shè)置為true,表示這個(gè)field被廢棄,應(yīng)該使用新代碼。大多數(shù)語(yǔ)言中,這個(gè)沒(méi)有任何影響。在java中,會(huì)生成@Deprecated的注釋。未來(lái),其它語(yǔ)言代碼在field的訪(fǎng)問(wèn)方法上也會(huì)生成相應(yīng)的注釋。 optional?int32?old_field?=?6? [ deprecated=true ] ;
  • 自定義options
protocol buffer還允許你自定義options。這是個(gè)高級(jí)特性,大多數(shù)人并不需要。options其實(shí)都定義在 google/protobuf/descriptor.proto文件中。 自定義的options是簡(jiǎn)單的,繼承這些messages import?"google/protobuf/descriptor.proto" ;
extend?google.protobuf.MessageOptions?{
??optional?string?my_option?=?51234 ;
}
message?MyMessage?{
??option?(my_option)?=?"Hello?world!" ;
} 這里我們定義了一個(gè)message級(jí)別的消息選項(xiàng),當(dāng)使用這個(gè)options的時(shí)候,選項(xiàng)的名稱(chēng)必須用括號(hào)括起來(lái),以表明它是一個(gè)extension。 我們?cè)贑++中讀取my_option的值就像下面這樣: string?value?=?MyMessage::descriptor()->options().GetExtension(my_option); 這里,MyMessage::descriptor()->options()返回的MessageOptions protocol類(lèi)型 message。 讀取自定義就如同讀取繼承屬性一樣。 在Java中 String?value?=?MyProtoFile.MyMessage.getDescriptor().getOptions().getExtension(MyProtoFile.myOption); 自定義options可以對(duì)任何message的組成元素進(jìn)行定義 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.EnumOptions?{
??optional?bool?my_enum_option?=?50003 ;
}
extend?google.protobuf.EnumValueOptions?{
??optional?uint32?my_enum_value_option?=?50004 ;
}
extend?google.protobuf.ServiceOptions?{
??optional?MyEnum?my_service_option?=?50005 ;
}
extend?google.protobuf.MethodOptions?{
??optional?MyMessage?my_method_option?=?50006 ;
}
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 ;
}
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" ;
??}
} 如果想使用在package里面的自定義的option,必須要option前使用包名,如下 //?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!" ;
} 最后一件事:既然自定義的options是extensions,他們必須指定field number就像其它field或者extension一樣。如果你要在公共應(yīng)用中使用自定義的options,那么一定要確認(rèn)你的field numbers是全局唯一的 你能通過(guò)多選項(xiàng)帶有一個(gè)extension 把它們放入一個(gè)子message中 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"?} ] ;
} 生成class代碼 為了生成java、python、C++代碼,你需要運(yùn)行protoc編譯器 protoc 編譯.proto文件。 編譯器運(yùn)行命令: protoc?--proto_path=IMPORT_PATH?--cpp_out=DST_DIR?--java_out=DST_DIR?--python_out=DST_DIR?path/to/file.proto import_path 查找proto文件的目錄,如果省略的話(huà),就是當(dāng)前目錄。存在多個(gè)引入目錄的話(huà),可以使用--proto_path參數(shù)來(lái)多次指定, -I=IMPORT_PATH就是--proto_path的縮寫(xiě) 輸出目錄 --cpp_out ? ? ? 生成C++代碼在DST_DIR目錄 --java_out ? ? ?生成Java代碼在DST_DIR目錄 --python_out ? ?生成Python代碼在DST_DIR目錄 有個(gè)額外的好處,如果DST是.zip或者.jar結(jié)尾,那么編譯器將會(huì)按照給定名字輸入到一個(gè)zip壓縮格式的文件中。 輸出到.jar會(huì)有一個(gè)jar指定的manifest文件。注意? 如果輸出文件已經(jīng)存在,它將會(huì)被覆蓋;編譯器的智能不足以自動(dòng)添加文件到一個(gè)存在的壓縮文件中。 你必須提供一個(gè)或者多個(gè).proto文件用作輸入。雖然文件命名關(guān)聯(lián)到當(dāng)前路徑,每個(gè)文件必須在import_path路徑中一邊編譯器能規(guī)定它的規(guī)范名稱(chēng)


更新message 如果一個(gè)message 不再滿(mǎn)足所有需要,需要對(duì)字段進(jìn)行調(diào)整.(舉例:對(duì)message增加一個(gè)額外的字段,但是仍然有支持舊格式message的代碼在運(yùn)行) 要注意以下幾點(diǎn):
1、不要修改已經(jīng)存在字段的數(shù)字順序標(biāo)示 2、可以增加optional或者repeated的新字段。這么做以后,所有通過(guò)舊格式message序列化的數(shù)據(jù)都可以通過(guò)新代碼來(lái)生成對(duì)應(yīng)的對(duì)象,正如他們不會(huì)丟失任何required元素。 你應(yīng)該為這些元素添加合理的默認(rèn)值,以便新代碼可以與舊代碼生成的消息交互。 新代碼創(chuàng)建的消息中舊代碼不存在的字段,在解析的時(shí)候,舊代碼會(huì)忽略掉新增的字段。 無(wú)論如何,未知的field不會(huì)被丟棄,如果message晚點(diǎn)序列化,為。 注意 未知field對(duì)于Python來(lái)說(shuō)當(dāng)前不可用。 3、非required字段都可以轉(zhuǎn)為extension ,反之亦然,只要type和number保持不變。 4、int32, uint32, int64, uint64, and bool 是全兼容的。這意味著你能改變一個(gè)field從這些類(lèi)型中的一個(gè)改變?yōu)榱硪粋€(gè),而不用考慮會(huì)打破向前、向后兼容性。 如果一個(gè)數(shù)字是通過(guò)網(wǎng)絡(luò)傳輸而來(lái)的相應(yīng)類(lèi)型轉(zhuǎn)換,你將會(huì)遇到type在C++中遇到的問(wèn)題(e.g. if a 64-bit number is read as an int32, it will be truncated to 32 bits) ? ? ? 5、sint32 and sint64 彼此兼容,但是不能兼容其它integer類(lèi)型. 6、string and bytes 在UTF-8編碼下是兼容的.? 7、如果bytes包含一個(gè)message的編碼,內(nèi)嵌message與bytes兼容. 8、fixed32 兼容 sfixed32, ?fixed64 兼容 sfixed64. 9、optional 兼容 repeated. 用一個(gè)repeat字段的編碼結(jié)果作為輸入,認(rèn)為這個(gè)字段是可選擇的客戶(hù)端會(huì)這樣處理,如果是原始類(lèi)型的話(huà),獲得最后的輸入作為相應(yīng)的option值;如果是message 類(lèi)型,合并所有輸入元素.? 10、更改默認(rèn)值通常是OK的.要記得默認(rèn)值并不會(huì)通過(guò)網(wǎng)絡(luò)發(fā)送,如果一個(gè)程序接受一個(gè)特定字段沒(méi)有設(shè)置值的消息,應(yīng)用將會(huì)使用自己的版本協(xié)議定義的默認(rèn)值,不會(huì)看見(jiàn)發(fā)送者的默認(rèn)值.

總結(jié)

以上是生活随笔為你收集整理的protocol buffer 使用之 .proto 定义规则的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。