syntax = "proto3";
文件的第一行指定了你使用的是proto3的語法:如果你不指定,protocol buffer 編譯器就會(huì)認(rèn)為你使用的是proto2的語法。這個(gè)語句必須出現(xiàn)在.proto文件的非空非注釋的第一行。message SearchRequest {......}
message 定義實(shí)體-
基本數(shù)據(jù)類型
image 注釋符號(hào): 雙斜線,如://xxxxxxxxxxxxxxxxxxx
字段唯一數(shù)字標(biāo)識(shí)(用于在二進(jìn)制格式中識(shí)別各個(gè)字段,上線后不宜再變動(dòng)):Tags
1到15使用一個(gè)字節(jié)來編碼,包括標(biāo)識(shí)數(shù)字和字段類型(你可以在Protocol Buffer 編碼中查看更多詳細(xì));16到2047占用兩個(gè)字節(jié)。因此定義proto文件時(shí)應(yīng)該保留1到15,用作出現(xiàn)最頻繁的消息類型的標(biāo)識(shí)。記得為將來會(huì)繼續(xù)增加并可能頻繁出現(xiàn)的元素留一點(diǎn)兒標(biāo)識(shí)區(qū)間,也就是說,不要一下子把1—15全部用完,為將來留一點(diǎn)兒。
標(biāo)識(shí)數(shù)字的合法范圍:最小是1,最大是 229 - 1,或者536,870,911。
另外,不能使用19000 到 19999之間的數(shù)字(FieldDescriptor::kFirstReservedNumber through FieldDescriptor::kLastReservedNumber),因?yàn)樗鼈儽籔rotocol Buffers保留使用字段修飾符:
required:值不可為空
optional:可選字段
singular:符合語法規(guī)則的消息包含零個(gè)或者一個(gè)這樣的字段(最多一個(gè))
repeated:(我把它理解為數(shù)組)一個(gè)字段在合法的消息中可以重復(fù)出現(xiàn)一定次數(shù)(包括零次)。重復(fù)出現(xiàn)的值的次序?qū)⒈槐A簟T趐roto3中,重復(fù)出現(xiàn)的值類型字段默認(rèn)采用壓縮編碼。你可以在這里找到更多關(guān)于壓縮編碼的東西: Protocol Buffer Encoding。
默認(rèn)值: optional PhoneType type = 2 [default = HOME];-
代理類生成
- C++, 每一個(gè).proto 文件可以生成一個(gè) .h 文件和一個(gè) .cc 文件
- Java, 每一個(gè).proto文件可以生成一個(gè) .java 文件
- Python, 每一個(gè).proto文件生成一個(gè)模塊,其中為每一個(gè)消息類型生成一個(gè)靜態(tài)的描述器,在運(yùn)行時(shí),和一個(gè)metaclass一起使用來創(chuàng)建必要的Python數(shù)據(jù)訪問類
- Go, 每一個(gè).proto生成一個(gè) .pb.go 文件
- Ruby, 每一個(gè).proto生成一個(gè) .rb 文件
- Objective-C, 每一個(gè).proto 文件可以生成一個(gè) pbobjc.h 和一個(gè)pbobjc.m 文件
- C#, 每一個(gè).proto文件可以生成一個(gè).cs文件.
-
字段默認(rèn)值
- strings, 默認(rèn)值是空字符串(empty string)
- bytes, 默認(rèn)值是空bytes(empty bytes)
- bools, 默認(rèn)值是false
- numeric, 默認(rèn)值是0
- enums, 默認(rèn)值是第一個(gè)枚舉值(value必須為0)
- message fields, the field is not set. Its exact value is langauge-dependent. See the generated code guide for details.
- repeated fields,默認(rèn)值為empty,通常是一個(gè)空list
-
枚舉
image第一個(gè)元素的value必須為0;
-
Maps字段類型:map<key_type, value_type> map_field = N;
- map字段不能是
repeated. - Wire format ordering and map iteration ordering of map values is undefined, so you cannot rely on your map items being in a particular order.
- When generating text format for a
.proto, maps are sorted by key. Numeric keys are sorted numerically. - When parsing from the wire or when merging, if there are duplicate map keys the last key seen is used. When parsing a map from text format, parsing will fail if there are duplicate keys.
- map字段不能是
-
更新.proto文件
當(dāng)原有的.proto結(jié)構(gòu)不能滿足業(yè)務(wù)需求時(shí),可以修改.proto文件,重新生成代理類,修改時(shí)需遵循以下原則:- 不能修改已存在字段的唯一數(shù)字標(biāo)識(shí)符(tags)
- If you add new fields, any messages serialized by code using your "old" message format can still be parsed by your new generated code. You should keep in mind the default values for these elements so that new code can properly interact with messages generated by old code. Similarly, messages created by your new code can be parsed by your old code: old binaries simply ignore the new field when parsing. Note that unknown fields are discarded when the message is deserialized, so if the message is passed on to new code, the new fields will not still be available (this is different behaviour to proto2, where unknown fields are serialized along with the message).
- 對(duì)廢棄的字段,它的tags不能被再次使用,可以不刪除,而是給字段添加“OBSOLETE_ ”前綴,這樣可以避免將來重新使用這個(gè)tags
- int32, uint32, int64, uint64, 和bool是完全兼容的,這些字段類型之間可以直接修改
- sint32 和 sint64 是兼容的,但是和其他的數(shù)字類型不兼容
- string 和 bytes 是兼容的,由于bytes也是 UTF-8格式
- Embedded messages are compatible with bytes if the bytes contain an encoded version of the message.
- fixed32 和 sfixed32兼容, fixed64和sfixed64兼容
- enum 和 int32, uint32, int64, and uint64 in terms of wire format (note that values will be truncated if they don't fit). However be aware that client code may treat them differently when the message is deserialized: for example, unrecognized proto3 enum types will be preserved in the message, but how this is represented when the message is deserialized is language-dependent. Int fields always just preserve their value.
Packages支持
定義Services
-
其他Options:
- java_package(file option):option java_package = "com.example.foo";
- java_outer_classname(file option ):option java_outer_classname = "Ponycopter";
- optimize_for(file option ):值為SPEED, CODE_SIZE或LITE_RUNTIME;如:option optimize_for = CODE_SIZE;
-
SPEED(default): The protocol buffer compiler will generate code for serializing, parsing, and performing other common operations on your message types. This code is extremely highly optimized. -
CODE_SIZE: The protocol buffer compiler will generate minimal classes and will rely on shared, reflection-based code to implement serialialization, parsing, and various other operations. The generated code will thus be much smaller than withSPEED, but operations will be slower. Classes will still implement exactly the same public API as they do inSPEEDmode. This mode is most useful in apps that contain a very large number.protofiles and do not need all of them to be blindingly fast. -
LITE_RUNTIME: The protocol buffer compiler will gener ate classes that depend only on the "lite" runtime library (libprotobuf-liteinstead oflibprotobuf). The lite runtime is much smaller than the full library (around an order of magnitude smaller) but omits certain features like descriptors and reflection. This is particularly useful for apps running on constrained platforms like mobile phones. The compiler will still generate fast implementations of all methods as it does inSPEEDmode. Generated classes will only implement theMessageLiteinterface in each language, which provides only a subset of the methods of the fullMessageinterface.
-
- cc_enable_arenas (file option ): 生成C++代碼時(shí)啟用arena allocation.
- objc_class_prefix (file option ): 設(shè)置 Objective-C class前綴,which is prepended to all Objective-C generated classes and enums from this .proto. There is no default. You should use prefixes that are between 3-5 uppercase characters as recommended by Apple. Note that all 2 letter prefixes are reserved by Apple.
- deprecated (field option): 如果設(shè)置為true,則該字段被置為“deprecated”,在新的代碼中不能被繼續(xù)使用,In most languages this has no actual effect. In Java, this becomes a @Deprecated annotation. In the future, other language-specific code generators may generate deprecation annotations on the field's accessors, which will in turn cause a warning to be emitted when compiling code which attempts to use the field. If the field is not used by anyone and you want to prevent new users from using it, consider replacing the field declaration with a reserved statement.
int32 old_field = 6 [deprecated=true];
示例:


