定義消息類型
話不多說首先我們來看一個非常簡單的例子。
定義一個查詢請求消息格式, 每個查詢請求有一個查詢語句窜护,為了減少一次查詢量睡腿,我們經常做分頁查詢,查詢結果的第幾頁/每頁結果數量爷光。如下:
syntax = "proto3";
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
- 第一行指明當前使用的是proto3語法, 如果不指定則默認為proto2垫竞。必須是.proto文件的除空行和注釋內容之外的第一行
- SearchRequest 消息定義指明了3個字段。每個字段有名字和類型.
字段類型
上面例子中, 所有字段都是Scalar Types/標量(通俗說基礎)類型(后面會詳細講述), 包括兩個int32和一個string. 此外還可以支持復合類型包括枚舉類型.
指定標簽
可以看到消息定義的每個字段都有一個唯一的數字型標簽. 這個標簽用于在消息的二進制格式中標識字段, 一旦消息類型被使用后不可以再修改.
標簽的值在1和15之間時編碼只需一個字節(jié)蛀序,包括標識值和字段類型欢瞪。標簽在16到2047之間將占用兩個字節(jié)。因此應該將從1到15的標簽分派給最頻繁出現(xiàn)的消息元素哼拔。記得保留一些空間給以后可能添加的頻繁出現(xiàn)的元素.
可以指定的最小的標簽值是1, 最大的是2的29次方-1, 即536870911引有。 另外19000到19999(FieldDescriptor::kFirstReservedNumber through FieldDescriptor::kLastReservedNumber)不能使用, 是Protocol Buffers的實現(xiàn)自己保留這個標簽段.
指定字段規(guī)則
消息字段可以是下列之一:
- singular: 一個定義良好的消息可以有0個或1個此字段(但是不能超過1個),該規(guī)則是V3版本默認規(guī)則
- repeated: 這個字段可以在定義好的消息中重復任意次(包括0次)倦逐,重復值的順序和原順序一致(類似于數組)譬正。
V3版本中,基礎類型定義額repeated會默認進行packed編碼以提高效率檬姥。例如:
repeated int32 samples = 4 [packed=true];
添加更多消息類型
可以在單個 .proto 文件中定義多個消息類型. 推薦定義多個相關消息, 例如, 如果你想定義應答消息格式來相應你的SearchResponse消息類型,建議放到同一個.proto文件.
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
message SearchResponse {
...
}
添加注釋
可以使用C/C++風格的"http://"語法在.proto文件中添加注釋曾我;或者"/****/"
/* SearchRequest represents a search query, with pagination options to
* indicate which results to include in the response. */
message SearchRequest {
string query = 1;
int32 page_number = 2; // Which page number do we want?
int32 result_per_page = 3; // Number of results to return per page.
}
保留字段
當你更新pb文件版本時,需要刪除一個字段時, 或者注釋掉它, 后續(xù)的新的接口版本重用這個標簽的數字健民,而已有的老版本程序仍然使用.proto文件的老版本,就會出現(xiàn)bug抒巢。 為了確保防止該bug產生, 我們可以指明這個要刪除的字段為保留字段.。如果未來任何用戶試圖復用這個字段標識protocol buffer的編譯器就會告警秉犹。
message Foo {
reserved 2, 15, 9 to 11;
reserved "foo", "bar";
}
注意: 不能在同一個保留字段聲明中混合使用名字和標簽數字
.proto可以生成什么?
對.proto文件執(zhí)行protocol buffer的編譯時蛉谜, 編輯器會生成你所選語言的代碼稚晚,用來處理你在文件中定義的消息類型, 包括讀寫字段值, 序列化消息到輸出流, 和從輸入流中解析消息.
- 對于c++, 編譯器為每個.proto文件生成.h和.cc文件, 并為每個在文件中描述的消息類型生成一個類
- 對于Java, 編譯器為每個消息類型生成一個.java文件, 還有用于創(chuàng)建消息實例的Builder類.
- Python小有不同 - Python編譯器為.proto文件中的每個消息類型生成帶有靜態(tài)描述符的模塊, 這些模塊將和metaclass一起在運行時用來創(chuàng)建必須的Python數據訪問類.
- 編譯器生成一個.pb.go文件, .proto文件中的每個消息類型在這個文件中都有一個類型.
- 對于Ruby, 編譯器生成一個.rb文件, 帶用包含消息類型的Ruby模塊.
- 對于JavaNano, 編譯器輸出類似java但是沒有builder類.
- 對于Objective-C, 編譯器從每個.proto文件生成一個pbobjc.h和pbobjc.m文件,文件中描述的每個消息類型都有一個類.
- 對于C#, 編譯器從每個.proto文件生成一個.cs文件,文件中描述的每個消息類型都有一個類.
- 對于Go語言,編譯器針對一個.proto文件生成一個pb.go文件型诚,為每個message生成一個類型