定義 Message 類型, 例子如下:
syntax = "proto3";
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.
}
說明:
1、proto3 格式的必須第一行指明版本號, syntax = "proto3";
2、所有的字段都是 Scalar Value Types
3、象上面看到的,所有的字段定義都有一個唯一的數字標簽,這些數字標簽用來標識在消息二進制序列化時的順序信息,序列化后,1~15占一個字節,16~2047占兩個字節。(字段的類型和識別號碼放在一起,下面可以看到 Scalar Value Types有15種,再加上標識號碼, 所以只能 1-15 占一個字節, 16以上2個字節)
所以你要注意,用1-15標識頻繁出現的元素。 標識號碼最小 1, 最大 is 229 - 1, 或者 536,870,911, 其中要排除 19000 到19999 這段保留段。
Scalar Value Types
在 proto 文件和各種語言中對應的類型關系如下圖:
這些類型的默認值如下:
- string 空字符串
- bytes 空 bytes
- bool 默認flase
- 數字類型 默認 0
- 枚舉類型 默認第一個值, 而且第一個的數字編碼必須是 0
- message fields 默認 null
- repeated 的字段默認是 null, 空的列表。
帶枚舉的一個message 例子:
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;
}
對枚舉來說, 如果設置了 option allow_alias = true; 就可以讓枚舉項的值一樣,相當於起了別名。
enum EnumAllowingAlias {
option allow_alias = true;
UNKNOWN = 0;
STARTED = 1;
RUNNING = 1;
}
定義引用
Message 可以使用其他 Message作為字段,即嵌套定義,比如下面定義:
message SearchResponse {
repeated Result result = 1;
}
message Result {
string url = 1;
string title = 2;
repeated string snippets = 3;
}
這里的 repeated 關鍵字相當於定義了一個對應的數組,數組元素是其后的類型, 數組的大小可以是0到很大, 由於歷史原因,數值型的repeated字段后面最好加上[packed=true],這樣能達到更好的編碼效果。
互相引用
如果 proto 文件定義不在這個文件, 我們可以通過下面方式引入:
import "myproject/other_protos.proto";
對於跨多個文件的引用, 這時候我們會用到 public 關鍵字, 它的用法如下:
// 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
public 的定義會一直嵌套帶入 import。
內部Message, 嵌套定義
你可以在 message 內部定義 message,如下面代碼:
message SearchResponse {
message Result {
string url = 1;
string title = 2;
repeated string snippets = 3;
}
repeated Result result = 1;
}
需要使用這個內部 message時,可以這么使用:
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;
}
}
}
最里面的兩個 message 的字段名稱一樣,只是字段類型不一樣。
參考資料:
Language Guide (proto3)
https://developers.google.com/protocol-buffers/docs/proto3?hl=zh-cn

