個人覺得,有谷歌翻譯让腹,百度翻譯远剩。加上自己的理解扣溺。自個看看官方文檔也還不錯骇窍。
下面98%是谷歌翻譯跟百度翻譯的。剩余2%是我自己按照自己的理解锥余。
免責(zé)聲明:粗糙翻譯腹纳,隨便看看哈。想糾正的。留言即可嘲恍。本人水平有限足画。
Overview(概覽)
這個頁面的內(nèi)容,你用谷歌翻譯看下佃牛。大概意思就是什么是protobuf淹辞?怎么怎么diao,然后跟xml一番對比俘侠。然后謙虛了一把(閱讀性不好象缀、自描述性不好),后面介紹了proto3爷速、protobuf歷史(它要解決什么問題)央星。
由于第一次使用主要就看proto3了。
proto3語言指南 (Language Guide proto3)
定義一個消息類型(Defining A Message Type)
syntax = "proto3";
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
- 如果不指定 syntax 為proto3 會認(rèn)為是proto2的語法惫东。
- SearchRequest消息定義了三個字段(name/value)莉给。每個字段對應(yīng)一個要包含在此類型消息中的數(shù)據(jù)。每個字段都有名字跟類型廉沮。
指定字段類型 && 分配字段編號
- 除了指定標(biāo)量類型颓遏,還可以指定復(fù)合類型(包括枚舉和其他類型)
- 分配字段編號 編號用于以消息二進(jìn)制格式標(biāo)識字段,并在使用消息類型后不應(yīng)更改废封。1~15占1個字節(jié)(包括字段編號和字段類型)州泊。16~2047占兩個字節(jié)。最小為1漂洋,最大為2^29-1或536,870,911不能使用19000到19999遥皂,這是保留字段
指定字段規(guī)則
單數(shù):格式良好的消息可以有零個或一個字段(但不能超過一個)。
重復(fù):此字段在格式良好的消息中可以重復(fù)任意次數(shù)(包括零)刽漂。將保留重復(fù)值的順序演训。
proto3中,repeated 標(biāo)量數(shù)字類型的字段使用packed作為默認(rèn)編碼贝咙。
關(guān)于編碼參考https://developers.google.com/protocol-buffers/docs/encoding?hl=zh-cn#packed
添加更多的消息類型
可以在一個.proto文件中定義多種消息類型样悟。如果要定義與SearchResponse消息類型對應(yīng)的答復(fù)消息格式,可以將其添加到相同的.proto:
注釋格式 /**/ //
保留字段
如果通過完全刪除字段或?qū)⑵渥⑨寔砀孪㈩愋屯バ桑瑒t未來用戶可以在對類型進(jìn)行自己的更新時重用字段編號窟她。如果以后加載舊版本的舊版本.proto,包括數(shù)據(jù)損壞蔼水,隱私錯誤等震糖,這可能會導(dǎo)致嚴(yán)重問題。指定已刪除字段的字段編號reserved趴腋。如果之后使用這些被刪除的字段吊说,編譯器會提示论咏。
不能在同一reserved語句中混合字段名稱和字段編號。
你的proto會生成什么
編譯proto根據(jù)你所選擇的語言颁井,根據(jù)消息類型的的描述生成到文件中厅贪。包含getting 跟setting filed values,序列化消息輸出流雅宾,通過輸入流解析消息养涮。
go生成的是.pb.go文件,每種消息都在這個文件中眉抬。
標(biāo)量值類型
.proto TYpe | GO Type | PHP Type |
---|---|---|
double | float64 | float |
float | float32 | float |
int32(如果有負(fù)數(shù)請使用sint32) | int32 | integer |
int64 | int64 | integer/string |
uint32 | uint32 | integer |
uint64 | uint64 | integer/string |
sint32 | int32 | integer |
sint64 | int64 | integer/string |
fixed32 | uint32 | integer |
fixed64 | unit64 | integer/string[ |
sfixed32 | int32 | integer |
sfixed64 | int64 | integer/string |
bool | bool | boolean |
string | String | string |
bytes | []byte | string |
Integer用于64位計算機(jī)单寂,字符串用于32位計算機(jī)。
默認(rèn)值
字符串吐辙,默認(rèn)為空字符串
字節(jié)宣决,默認(rèn)為空字節(jié)
bool 默認(rèn)為false
數(shù)值類型,默認(rèn)為0值
枚舉類型昏苏,默認(rèn)為第一個枚舉值(必須為0)
對于消息字段尊沸,字段沒有設(shè)置。具體的值取決于具體的語言贤惯。
重復(fù)的字段默認(rèn)值為空洼专。
請注意,對于標(biāo)量消息字段孵构,一旦解析了消息屁商,就無法判斷字段是否顯式設(shè)置為默認(rèn)值(例如布爾值是否設(shè)置為false),或者根本沒有設(shè)置:在定義消息類型時颈墅,應(yīng)該記住這一點(diǎn)蜡镶。例如,如果您不希望某些行為在默認(rèn)情況下也發(fā)生恤筛,則不要使用布爾值在設(shè)置為false時打開某些行為官还。還要注意,如果將標(biāo)量消息字段設(shè)置為其默認(rèn)值毒坛,則該值將不會在線路上序列化望伦。
有關(guān)默認(rèn)值如何在生成的代碼中工作的更多詳細(xì)信息,請參閱所選語言的生成代碼指南煎殷。
枚舉
在定義消息類型時屯伞,您可能希望其中一個字段只有一個預(yù)定義的值列表。
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;
}
每個枚舉定義必須包含一個映射到零的常量作為其第一個元素豪直。這是因?yàn)椋?/p>
必須有一個零值劣摇,以便我們可以使用0作為數(shù)字默認(rèn)值。
零值必須是第一個元素顶伞,以便與proto2語義兼容饵撑,其中第一個枚舉值始終是默認(rèn)值。
您可以通過為不同的枚舉常量指定相同的值來定義別名唆貌。為此滑潘,您需要將allow_alias選項(xiàng)設(shè)置為true,否則協(xié)議編譯器將在找到別名時生成錯誤消息锨咙。
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位整數(shù)的范圍內(nèi)语卤。由于枚舉值在線路上使用變量編碼,因此負(fù)值效率很低酪刀,因此不推薦使用粹舵。您可以在消息定義中定義枚舉,如上面的示例中所示骂倘,也可以在外部定義-這些枚舉可以在.proto文件中的任何消息定義中重用眼滤。還可以使用一條消息中聲明的枚舉類型作為另一條消息中字段的類型,使用語法message type.enum type历涝。
在反序列化過程中诅需,消息中將保留無法識別的枚舉值,盡管反序列化消息時如何表示枚舉值取決于語言荧库。在支持具有指定符號范圍之外的開放枚舉類型的語言(如C++和GO)中堰塌,未知的枚舉值僅作為其基礎(chǔ)的整數(shù)表示形式存儲。在具有封閉枚舉類型的語言(如Java)中分衫,枚舉中的一個實(shí)例用于表示未識別的值场刑,而基礎(chǔ)的整數(shù)可以用特殊的訪問器訪問。在這兩種情況下蚪战,如果消息被序列化牵现,則無法識別的值仍將用消息序列化。
保留值
如果通過完全刪除枚舉項(xiàng)或?qū)⑵渥⑨尩魜砀旅杜e類型邀桑,將來的用戶可以在對該類型進(jìn)行自己的更新時重用該數(shù)值施籍。如果他們以后加載相同的.proto的舊版本,這可能會導(dǎo)致嚴(yán)重的問題概漱,包括數(shù)據(jù)損壞丑慎、隱私錯誤等。確保不會發(fā)生這種情況的一種方法是指定保留已刪除條目的數(shù)值(和/或名稱瓤摧,這也可能導(dǎo)致JSON序列化問題)竿裂。如果將來有任何用戶試圖使用這些標(biāo)識符,協(xié)議緩沖區(qū)編譯器將發(fā)出投訴照弥∧逡欤可以使用max關(guān)鍵字指定保留的數(shù)值范圍達(dá)到最大可能值。
enum Foo {
reserved 2, 15, 9 to 11, 40 to max;
reserved "FOO", "BAR";
}
使用其他消息類型
您可以使用其他消息類型作為字段類型这揣。例如悔常,假設(shè)您希望在每個SearchResponse消息中包含結(jié)果消息–為此影斑,可以在相同的.proto中定義結(jié)果消息類型,然后在SearchResponse中指定類型為result的字段:
message SearchResponse {
repeated Result results = 1;
}
message Result {
string url = 1;
string title = 2;
repeated string snippets = 3;
}
import
import "myproject/other_protos.proto";
默認(rèn)情況下机打,只能使用直接導(dǎo)入的.proto文件中的定義矫户。但是,有時可能需要將.proto文件移動到新位置〔醒現(xiàn)在皆辽,您可以在舊位置放置一個虛擬的.proto文件,使用import public概念將所有導(dǎo)入轉(zhuǎn)發(fā)到新位置芥挣,而不是直接移動.proto文件并在一次更改中更新所有調(diào)用站點(diǎn)驱闷。任何導(dǎo)入包含import public語句的協(xié)議的人都可以傳遞依賴import public依賴項(xiàng)。
// new.proto
// All definitions are moved here
// old.proto
// This is the proto that all clients are importing.
import public "new.proto";
import "other.proto";
// client.proto
import "old.proto";
// You use definitions from old.proto and new.proto, but not other.proto
protocol編譯器(protoc命令) 根據(jù) -I/--proto_path到指定的目錄下找導(dǎo)入的文件空免。如果沒有指定就到編譯器目錄下查找空另。通常你應(yīng)該將項(xiàng)目的根目錄設(shè)置給--proto_path,并對所有導(dǎo)入使用完全限定的名稱蹋砚。
可以導(dǎo)入proto2消息類型在proto3中使用痹换。反之亦然。
嵌套類型
你可以在其他消息類型中定義和使用消息類型都弹。
message SearchResponse {
message Result {
string url = 1;
string title = 2;
repeated string snippets = 3;
}
repeated Result results = 1;
}
如果要在其父消息類型之外復(fù)用此消息類型娇豫,請將其稱為: Parent.Type
。
message SomeOtherMessage {
SearchResponse.Result result = 1;
}
深層嵌套
message Outer { // Level 0
message MiddleAA { // Level 1
message Inner { // Level 2
int64 ival = 1;
bool booly = 2;
}
}
message MiddleBB { // Level 1
message Inner { // Level 2
int32 ival = 1;
bool booly = 2;
}
}
}
更新消息類型
如果一個現(xiàn)有的消息類型不再滿足您的所有需求——例如畅厢,您希望消息格式有一個額外的字段——但是您仍然希望使用用舊格式創(chuàng)建的代碼冯痢,不要擔(dān)心!在不破壞任何現(xiàn)有代碼的情況下更新消息類型非常簡單框杜。記住以下規(guī)則:
- 不要更改任何現(xiàn)有字段的字段編號浦楣。
- 如果添加新字段,則使用“舊”消息格式的代碼序列化的任何消息仍然可以由新生成的代碼解析咪辱。您應(yīng)該記住這些元素的默認(rèn)值振劳,以便新代碼可以與舊代碼生成的消息正確交互。同樣油狂,由新代碼創(chuàng)建的消息可以由舊代碼解析:舊二進(jìn)制文件在解析時只忽略新字段历恐。有關(guān)詳細(xì)信息,請參閱“未知字段”部分专筷。
- 只要在更新的消息類型中不再使用字段編號弱贼,就可以刪除字段。您可能需要重命名字段磷蛹,或者添加前綴“obsolete_u”吮旅,或者保留字段編號,這樣.proto的未來用戶就不能意外地重用該編號味咳。
- int32庇勃、uint32檬嘀、int64、uint64和bool都是兼容的——這意味著您可以在不中斷向前或向后兼容性的情況下將字段從這些類型中的一種更改為另一種责嚷。如果從一個不適合于相應(yīng)類型的線中解析一個數(shù)鸳兽,那么您將得到與在C++中將該數(shù)轉(zhuǎn)換為該類型的相同的效果(例如,如果一個64位的數(shù)字被讀取為一個IT32再层,它將被截斷到32位)。
- sint32和sint64彼此兼容堡纬,但與其他整數(shù)類型不兼容聂受。
- 只要字節(jié)是有效的UTF-8,字符串和字節(jié)就可以兼容烤镐。
- 如果字節(jié)包含消息的編碼版本蛋济,則嵌入消息與字節(jié)兼容。
- fixed32與sfixed32兼容炮叶,fixed64與sfixed64兼容碗旅。
- Enum在Wire格式方面與Int32、UInt32镜悉、Int64和UInt64兼容(請注意祟辟,如果值不匹配,則會被截斷)侣肄。但是旧困,請注意,當(dāng)消息被反序列化時稼锅,客戶端代碼可能會對它們進(jìn)行不同的處理:例如吼具,消息中將保留無法識別的proto3枚舉類型,但是當(dāng)消息被反序列化時矩距,如何表示這些枚舉類型取決于語言拗盒。int字段總是保留其值。
- 將單個值更改為新的oneof成員是安全的锥债,并且與二進(jìn)制兼容陡蝇。如果您確定一次沒有設(shè)置多個代碼,那么將多個字段移動到新的字段中可能是安全的哮肚。將任何字段移動到現(xiàn)有的某個字段中是不安全的毅整。
未知字段
未知字段是格式良好的協(xié)議緩沖區(qū)序列化數(shù)據(jù),表示解析程序無法識別的字段绽左。例如悼嫉,當(dāng)一個舊的二進(jìn)制文件用新字段解析新二進(jìn)制文件發(fā)送的數(shù)據(jù)時,這些新字段就變成舊二進(jìn)制文件中的未知字段拼窥。
最初戏蔑,Proto3消息在解析過程中總是丟棄未知字段蹋凝,但在3.5版中,我們重新引入了保留未知字段以匹配Proto2行為总棵。在3.5及更高版本中鳍寂,解析期間會保留未知字段,并包含在序列化輸出中情龄。
Any
any消息類型允許您將消息用作嵌入類型迄汛,而不需要它們的.proto定義。any包含一個任意的序列化消息(以字節(jié)為單位)骤视,以及一個充當(dāng)該消息類型的全局唯一標(biāo)識符并解析為該消息類型的URL鞍爱。要使用任何類型,您需要導(dǎo)入google/protobuf/any.proto专酗。
import "google/protobuf/any.proto";
message ErrorStatus {
string message = 1;
repeated google.protobuf.Any details = 2;
}
不同語言提供了pack跟unpack 的運(yùn)行時庫用于any values睹逃。java中有pack() 、unpack()祷肯,C++ 有PackFrom() 沉填、UnpackTo()。
如果您已熟悉proto2語法佑笋,則Any類型將替換擴(kuò)展轧葛。
Oneof
如果您有一條包含多個字段的消息蚀乔,并且在同一時間最多設(shè)置一個字段屈雄,則可以使用one-of功能強(qiáng)制執(zhí)行此行為并保存內(nèi)存蒋得。
Setting any member of the oneof automatically clears all the other members. You can check which value in a oneof is set (if any) using a special case() or WhichOneof() method, depending on your chosen language
除了所有的字段共享一個oneof內(nèi)存外,Oneof字段跟常規(guī)字段類似颠锉,并最多同時設(shè)置一個字段法牲。設(shè)置其中一個字段就會清理掉其他成員。根據(jù)所選語言琼掠,你可以使用case()或者WhichOneof方法檢查oneof值的設(shè)置拒垃。
使用oneof
oneof后面跟名稱
message SampleMessage {
oneof test_oneof {
string name = 4;
SubMessage sub_message = 9;
}
}
然后將一個字段添加到定義中。您可以添加任何類型的字段瓷蛙,但不能使用repeated field悼瓮。
在生成的代碼中,oneof字段與常規(guī)字段具有相同的getter和setter艰猬。還會有專門方法來檢查oneof中的值.
Oneof 特點(diǎn)
- 設(shè)置一個oneof字段會自動清理掉其他oneof的成員横堡。如果你設(shè)置了幾個oneof字段,只有最后一個字段會有值冠桃。
SampleMessage message;
message.set_name("name");
CHECK(message.has_name());
message.mutable_sub_message(); // Will clear name field.
CHECK(!message.has_name());
如果解析器在線路上遇到同一個的多個成員命贴,則在解析的消息中只使用看到的最后一個成員。
oneof不能為 repeated
反射API適用于oneof字段。
向后兼容性問題
添加或刪除其中一個字段時要小心胸蛛。如果檢查oneof的值返回None/NOT_SET污茵,則可能意味著oneof尚未設(shè)置,或者已設(shè)置為oneof的其他版本中的字段葬项。沒有辦法區(qū)別泞当,因?yàn)闆]有辦法知道線路上的未知字段是否是其中一個的成員。
標(biāo)簽復(fù)用問題
將字段移入或移出 oneof:在消息序列化和分析之后民珍,可能會丟失某些信息(某些字段將被清除)襟士。不管怎樣,你可以安全的移動單個字段到oneof中嚷量,如果你知道只會有一個字段會被設(shè)置陋桂,也可以移動多個字段。
刪除oneof字段并將其添加回:這可能會在序列化和分析消息后清除當(dāng)前設(shè)置的oneof字段津肛。
拆分或合并oneof:這與移動常規(guī)字段有類似的問題章喉。
Map
如果要在數(shù)據(jù)定義中創(chuàng)建關(guān)聯(lián)映射汗贫,Protobuf提供了一種方便的快捷方式語法:
map<key_type, value_type> map_field = N;
- map字段不能是repeated
- 報文格式排序和map值的迭代排序未定義身坐,因此不能依賴于特定順序中的map項(xiàng)。
- .proto生成文本格式時落包,map按鍵排序部蛇。數(shù)字鍵按數(shù)字順序排列。
- 從報文中解析和合并時咐蝇,如果存在重復(fù)的map key涯鲁,則使用最后一個。當(dāng)從文本中解析一個map有序,存在重復(fù)的key則可能會失敗抹腿。
如果map字段提供鍵但沒有值,則字段序列化時的行為取決于語言旭寿。在C++警绩、Java和Python中,該類型的默認(rèn)值被序列化盅称,而在其他語言中肩祥,沒有任何序列化。
向后兼容性問題
map語法在報文中等同于下面的內(nèi)容缩膝,因此不支持map的protobuf也是可以處理你的數(shù)據(jù)的:
message MapFieldEntry {
key_type key = 1;
value_type value = 2;
}
repeated MapFieldEntry map_field = N;
包 (Packages)
可以向.proto文件添加可選的包說明符混狠,以防止協(xié)議消息類型之間的名稱沖突。
package foo.bar;
message Open { ... }
然后疾层,在定義消息類型的字段時将饺,可以使用包說明符:
message Foo {
...
foo.bar.Open open = 1;
...
}
包說明符影響生成代碼的方式取決于所選語言(這里只看go):
- 在go中,包被用作go包的名稱,除非在.proto文件中顯式地提供一個選項(xiàng)go_package俯逾。
包和名稱解析
包和名稱解析
協(xié)議緩沖區(qū)中的類型名稱解析像C++一樣工作:首先搜索最內(nèi)層的范圍贸桶,然后搜索最內(nèi)層的,等等桌肴,每個包都被認(rèn)為是“內(nèi)部的”到它的父包皇筛。前導(dǎo)“.”(例如,.foo.bar.baz)表示從最外面的作用域開始坠七。
協(xié)議緩沖區(qū)編譯器通過分析導(dǎo)入的.proto文件解析所有類型名水醋。每種語言的代碼生成器都知道如何引用該語言中的每種類型,即使它有不同的作用域規(guī)則彪置。
定義服務(wù)
如果要將消息類型與RPC(遠(yuǎn)程過程調(diào)用)系統(tǒng)一起使用拄踪,可以在.proto文件中定義一個RPC服務(wù)接口,協(xié)議緩沖區(qū)編譯器將以所選語言生成服務(wù)接口代碼和stub拳魁。因此惶桐,例如,如果要使用接收SearchRequest并返回SearchResponse的方法定義RPC服務(wù)潘懊,可以在.proto文件中定義它姚糊,如下所示:
service SearchService {
rpc Search (SearchRequest) returns (SearchResponse);
}
與協(xié)議緩沖區(qū)一起使用的最簡單的RPC系統(tǒng)是GRPC:一個在谷歌開發(fā)的語言和平臺無關(guān)的開源RPC系統(tǒng)。GRPC特別適用于協(xié)議緩沖區(qū)授舟,允許您使用特殊的協(xié)議緩沖區(qū)編譯器插件直接從.proto文件生成相關(guān)的RPC代碼救恨。
如果不想使用GRPC,也可以將協(xié)議緩沖區(qū)與您自己的RPC實(shí)現(xiàn)一起使用释树。你可以在Proto2語言指南中找到更多關(guān)于這個的信息肠槽。
還有許多正在進(jìn)行的第三方項(xiàng)目,用于開發(fā)協(xié)議緩沖區(qū)的RPC實(shí)現(xiàn)奢啥。有關(guān)我們知道的項(xiàng)目的鏈接列表秸仙,請參閱第三方附加組件wiki頁面。
JSON映射
Proto3支持JSON中的規(guī)范編碼桩盲,使得在系統(tǒng)之間共享數(shù)據(jù)變得更加容易寂纪。在下表中逐個類型地描述編碼。
如果JSON編碼數(shù)據(jù)中缺少值或其值為null正驻,則在解析為protobuf 時弊攘,它將被解釋為適當(dāng)?shù)哪J(rèn)值。如果字段在protobuf 中具有默認(rèn)值姑曙,則默認(rèn)情況下將在JSON編碼的數(shù)據(jù)中省略該字段以節(jié)省空間襟交。實(shí)現(xiàn)可以提供用于在JSON編碼的輸出中發(fā)出具有默認(rèn)值的字段的選項(xiàng)。
這個表我沒粘貼伤靠,自個去官網(wǎng)上看吧捣域。
JSON選項(xiàng)
Proto3 JSON實(shí)現(xiàn)可以提供以下選項(xiàng):
- 使用默認(rèn)值發(fā)出字段:Proto3 JSON輸出中默認(rèn)忽略具有默認(rèn)值的字段啼染。實(shí)現(xiàn)可以提供一個選項(xiàng),用其默認(rèn)值覆蓋此行為和輸出字段焕梅。
- 忽略未知字段:Proto3 JSON解析器默認(rèn)情況下應(yīng)拒絕未知字段迹鹅,但可能提供在解析時忽略未知字段的選項(xiàng)。
- 使用proto字段名而不是lowercamelcase名稱:默認(rèn)情況下贞言,proto3 json打印機(jī)應(yīng)將字段名轉(zhuǎn)換為lowercamelcase斜棚,并將其用作json名稱。實(shí)現(xiàn)可以提供一個選項(xiàng)來使用proto字段名作為JSON名稱该窗。Proto3 JSON解析器需要接受轉(zhuǎn)換后的lowercamelcase名稱和Proto字段名稱弟蚀。
- 將枚舉值作為整數(shù)而不是字符串發(fā)出:默認(rèn)情況下,在JSON輸出中使用枚舉值的名稱酗失∫宥ぃ可以提供一個選項(xiàng)來使用枚舉值的數(shù)值。
選項(xiàng)
.proto文件中的單個聲明可以用許多選項(xiàng)進(jìn)行注釋规肴。選項(xiàng)不會改變聲明的整體含義捶闸,但可能影響在特定上下文中處理聲明的方式⊥先校可用選項(xiàng)的完整列表在google/protobuf/descriptor.proto中定義删壮。
有些選項(xiàng)是文件級選項(xiàng),這意味著它們應(yīng)該在頂級范圍內(nèi)寫入序调,而不是在任何消息醉锅、枚舉或服務(wù)定義內(nèi)寫入兔簇。有些選項(xiàng)是消息級選項(xiàng)发绢,這意味著它們應(yīng)該寫在消息定義中。有些選項(xiàng)是字段級選項(xiàng)垄琐,這意味著它們應(yīng)該寫在字段定義中边酒。還可以在枚舉類型、枚舉值狸窘、服務(wù)類型和服務(wù)方法上編寫選項(xiàng)墩朦;但是,目前沒有任何有用的選項(xiàng)可用于這些類型翻擒。
生成你的類
編譯示例:
protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --java_out=DST_DIR --python_out=DST_DIR --go_out=DST_DIR --ruby_out=DST_DIR --objc_out=DST_DIR --csharp_out=DST_DIR path/to/file.proto
- IMPORT_PATH指定.proto解析import指令時在其中查找文件的目錄氓涣。如果省略,則使用當(dāng)前目錄陋气±头停可以通過--proto_path多次傳遞選項(xiàng)來指定多個導(dǎo)入目錄; 他們將按順序搜索。 可以用作簡短的形式巩趁。 -I=IMPORT_PATH--proto_path
** --go_out生成Go代碼DST_DIR痒玩。有關(guān)更多信息,請參閱Go生成代碼參考。
** --php_out生成PHP代碼DST_DIR蠢古∨铮看到PHP生成的代碼的參考更多。
- 您必須提供一個或多個.proto文件作為輸入草讶。.proto可以一次指定多個文件洽糟。雖然文件是相對于當(dāng)前目錄命名的,但每個文件必須駐留在其中一個文件中堕战,IMPORT_PATH以便編譯器可以確定其規(guī)范名稱脊框。
風(fēng)格指南(style guide)
下面是.proto文件的風(fēng)格指南。遵循這些約定践啄,可以讓你的protobuf 消息定義以及相應(yīng)的類保持一致并易于閱讀:
文件格式標(biāo)準(zhǔn)(Standard file formatting)
- 每行保持80個字符
- 縮進(jìn)采用兩個空格
文件結(jié)構(gòu)(File structure)
文件命名如lower_snake_case.proto
(小寫蛇形命名法浇雹,下劃線命名)
文件中要保持如下的順序(書寫順序):
- 許可證
2.文件概述
3.Syntax (指定proto版本)
4.包(package)
5.import
6.File options
7.其他
包(packages)
包名稱應(yīng)為小寫,并且應(yīng)與目錄層次結(jié)構(gòu)相對應(yīng)屿讽。例如昭灵,如果文件在my/package/,則包名稱應(yīng)為my.package伐谈。
消息和字段名稱(Message and field names)
消息名稱采用大寫駝峰(CamelCase)烂完。字段名稱采用下劃線分割名稱(underscore_separated_names)
message SongServerRequest {
required string song_name = 1;
}
據(jù)此生成后的代碼中訪問方法如下:
C++:
const string& song_name() { ... }
void set_song_name(const string& x) { ... }
Java:
public String getSongName() { ... }
public Builder setSongName(String v) { ... }
Go中類似如下:
func (m *Person_PhoneNumber) GetNumber() string {
if m != nil {
return m.Number
}
return ""
}
func (m *Person_PhoneNumber) GetType() Person_PhoneType {
if m != nil {
return m.Type
}
return Person_MOBILE
}
如果您的字段名稱包含數(shù)字,則該數(shù)字應(yīng)顯示在字母后面而不是下劃線之后诵棵。例如抠蚣,用song_name1而不是song_name_1。
Repeated fields
對重復(fù)的字段使用復(fù)數(shù)名稱(可以理解為是數(shù)組)履澳。
repeated string keys = 1;
...
repeated MyMessage accounts = 17;
枚舉
對于枚舉類型名稱使用CamelCase嘶窄,值命名采用CAPITALS_WITH_UNDERSCORES
enum Foo {
FOO_UNSPECIFIED = 0;
FOO_FIRST_VALUE = 1;
FOO_SECOND_VALUE = 2;
}
每個枚舉值應(yīng)以分號結(jié)束,而不是逗號距贷。更喜歡為枚舉值添加前綴柄冲,而不是將其包圍在封閉消息中。零值枚舉應(yīng)具有后綴缺省忠蝗。
Services(服務(wù))
如果您.proto定義了RPC服務(wù)现横,則應(yīng)將CamelCase(首字母大寫)用于服務(wù)名稱和任何RPC方法名稱:
service FooService {
rpc GetSomething(FooRequest) returns (FooResponse);
}
參考資料:
- 《protoc2 與 protoc3 區(qū)別》http://www.reibang.com/p/cdedcf696e9e