一般,編寫一個protocol buffers應用需要經歷例如如下三步:數組
首先咱們可以經過Google在線文檔上提供的一個電話簿的樣例來了解下。只是略微加了點修改。
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
required bytes unsure = 5; //Add byte array here
}
message AddressBook {
repeated Person person = 1;
}
誠如你看到的同樣,消息格式定義很是easy。對於每個字段而言都有一個修飾符(required/repeated/optional)、字段類型(bool/string/bytes/int32等)和字段標籤(Tag)組成。
三個修飾符從詞義上可以很是清楚的弄明確。
1)對於required的字段而言,初值是必須要提供的,不然字段的即是未初始化的。網絡
在Debug模式的buffer庫下編譯的話,序列化話的時候可能會失敗,而且在反序列化的時候對於該字段的解析會老是失敗的。因此,對於修飾符爲required的字段,請在序列化的時候務必給予初始化。函數
2)對於optional的字段而言,假設未進行初始化。那麼一個默認值將賦予該字段。固然也可以指定默認值。如上述proto定義中的PhoneType字段類型。
3)對於repeated的字段而言,該字段可以反覆多個,google提供的這個addressbook樣例便有個很是好的該修飾符的應用場景,即每個人可能有多個電話號碼。在高級語言裏面,咱們可以經過數組來實現,而在proto定義文件裏可以使用repeated來修飾,從而達到一樣目的。固然。出現0次也是包括在內的。ui
當中字段標籤標示了字段在二進制流中存放的位置,這個是必須的,而且序列化與反序列化的時候一樣的字段的Tag值必須相應,不然反序列化會出現意想不到的問題。
google
3、編譯proto文件。生成特定語言數據的數據定義代碼 指針
經過查看頭文件,可以發現針對每個字段都會大體生成例如如下幾種函數,以number爲例:
// required string number = 1;
inline bool has_number() const;
inline void clear_number();
inline const ::std::string& number() const;
inline void set_number(const ::std::string& value);
inline void set_number(const char* value);
inline ::std::string* mutable_number();
可以看出。對於每個字段會生成一個has函數(has_number)、clear清除函數(clear_number)、set函數(set_number)、get函數(number和mutable_number)。這兒解釋下get函數中的兩個函數的差異,對於原型爲const std::string &number() const的get函數而言,返回的是常量字段,不能對其值進行改動。但是在有一些狀況下,對字段進行改動是必要的。因此提供了一個mutable版的get函數,經過獲取字段變量的指針,從而達到改變其值的目的。
而對於字段修飾符爲repeated的字段生成的函數。則略微有一些不一樣,如phone字段,則編譯器會爲其產生例如如下的代碼:
// repeated .Person.PhoneNumber phone = 4;
inline int phone_size() const;
inline void clear_phone();
inline const ::google::protobuf::RepeatedPtrField< ::Person_PhoneNumber >& phone() const;
inline ::google::protobuf::RepeatedPtrField< ::Person_PhoneNumber >* mutable_phone();
inline const ::Person_PhoneNumber& phone(int index) const;
inline ::Person_PhoneNumber* mutable_phone(int index);
inline ::Person_PhoneNumber* add_phone();
可以看出,set函數變成了add函數,這個事實上很是好理解。code
上面也說過。repeated修飾的字段在高級語言中的實現多是個數組或動態數組,因此固然經過加入的方式來加入新的字段值。而起get函數也變化很是大。這個也不用多說了。
文檔
好了。本文主要是對了解protocol buffer做了些簡單的介紹,固然更具體的仍是看官方文檔。get