介紹一下訊息的不同型別和引用
使用複雜訊息型別
您可以使用其他訊息型別作為欄位型別。例如,假設你想在每個SearchResponse
訊息中包含Result
訊息,您可以在同一個.proto
中定義一個Result
訊息型別,然後在SearchResponse
中指定一個Result
型別的欄位:
message SearchResponse {
repeated Result results = 1;
}
message Result {
string url = 1;
string title = 2;
repeated string snippets = 3;
}複製程式碼
引入其他訊息檔案
在上述示例中,Result
訊息型別與SearchResponse
在相同的檔案中定義, 如果要使用的訊息型別已經在另一個.proto
檔案中定義了怎麼解決呢?
你可以通過import
引入其他的.proto
檔案:
import "myproject/other_protos.proto";複製程式碼
注意
接上邊的例子,假如a.proto
引入了b.proto
,但是b.proto
更換了位置,路徑變成了test/b.proto
(隨便舉例),我們有兩種解決辦法:
- 修改
a.proto
中的import
語句,直接import "test/b.proto"
- 在
b.proto
檔案原來的位置,建立一個b.proto
檔案,檔案內容為import public "test/b.proto"
,就可以了
import
對proto2
和proto3
都適用
巢狀型別
您可以在其他訊息型別中定義和使用訊息型別,如下,Result
訊息定義在SearchResponse
訊息中:
message SearchResponse {
message Result {
string url = 1;
string title = 2;
repeated string snippets = 3;
}
repeated Result results = 1;
}複製程式碼
如果想重複使用Result
,可以用Parent.Type
的方式使用:
message AnotherResponse {
SearchResponse.Result res = 1;
}複製程式碼
修改更新現有的訊息格式
修改時要注意的規則:
- 不要改變已經存在欄位的標籤
- 新增一個欄位時,舊的訊息將會收到這個欄位的預設值
- 刪除一個欄位時,記得把該欄位的標籤新增到
reserved
裡 - int32,uint32,int64,uint64和bool都是相容的。這意味著您可以將這些型別之一的欄位更改為另一個,而不會破壞前向或後向相容性。轉換過程相當於C ++中將該數字轉換為該型別(例如,如果將64位數字讀為int32, 它將被截斷到32位)
- sint32和sint64相互相容,但與其他整數型別不相容
- 只要位元組是有效的UTF-8,字串和位元組是相容的
- 巢狀訊息(message)與包含訊息的編碼版本的位元組(bytes)相容【表述不清,歡迎大家評論指正】
- fixed32與sfixed32相容,fixed64與sfixed64相容
- 列舉相容int32,uint32,int64和uint64(請注意,如果值不合適,那麼值將被截斷)。 但是請注意,客戶端程式碼可以在訊息反序列化時對它們進行不同的處理:例如,訊息中將保留無法識別的proto3列舉型別,但是當訊息反序列化時,如何處理和使用的程式語言相關。 Int欄位始終保持其值
Any
型別
any型別時谷歌protobuf內建的一個型別,通用型別,使用的時候需要匯入google/protbuf/any.proto
import "google/protobuf/any.proto";
message ErrorStatus {
string message = 1;
repeated google.protobuf.Any details = 2;
}複製程式碼
Oneof
型別
Oneof結構中有多個欄位,但是同一時刻只有一個欄位生效
定義oneof結構
message SampleMessage {
oneof test_oneof {
string name = 4;
SubMessage sub_message = 9;
}
}複製程式碼
oneof中可以是任意型別,除了repeated 欄位
生成程式碼之後,也會對oneof欄位生成getter,setter方法,但是出來的值需要你自己判斷一下
Maps 型別
如果你要定義一個map,protobuf提供了一個語法:
map<key_type, value_type> map_field = N;複製程式碼
例如
map<string, Project> projects = 3;複製程式碼
注意事項
- Map欄位不能是
repeated
- Map中的集合是無序的
.proto
檔案生成時,map按key排序- 解析或者合併時,後邊的會覆蓋前邊的
packages語法
你可以新增一個可選標識package
到.proto
檔案中。用來防止命名衝突
package foo.bar;
message Open { ... }複製程式碼
在使用這條訊息的時候需要加上package
名字
message Foo {
...
foo.bar.Open open = 1;
...
}複製程式碼