Protobuf grammar
gRPC recommended proto3, this section only describes the common syntax, the use of more advanced gestures refer to the official documentation
Message definitions
A message definition describes a request type or corresponding message format may comprise a plurality of field types. E.g. define a search request message format, each request contains a query string, the page number, page number.
syntax = "proto3";
message SearchRequest {
string query = 1; // 查询字符串 int32 page_number = 2; // 页码 int32 result_per_page = 3; // 每页条数 }
protobuf version of the first line of the Statement of proto3
SearchRequest defines three fields, each field declarations end with a semicolon, the double slash can be used //
to add comments.
Field type declaration
All the fields need to pre-declared data type, two examples of the above specified type, and a numeric string type. In addition to the basic types of scalar type as well as a composite, such as enumeration, other message types.
Identifier Tags
Can be seen, the definition of the message, each field has a unique numeric identifier. These identifiers are used in the binary format identifier field in the message, the type used should not be altered arbitrarily. Note that, the identification [1-15] in the coding only occupies one byte, contains the identifier and field types. Between [16-2047] Identifier 2 bytes. Recommended usage identifier [1-15] is a message between frequently occurring elements. May be extended or frequent after considering the elements, you can set aside some identifier.
Smallest identifier may start from a maximum to 229--1, or 536,870,911. Identifier can not be used between the [19000-19999], Protobuf these protocol identifiers is reserved. Using these reserved identification number .proto file then compile-time error.
Field Rules
-
repeated: identification field may be repeated any number of times, similar to the array
-
proto3 does not support the required and optional proto2
Add more message types
.Proto a file can define multiple message types, typically for simultaneously defining a plurality of related messages, for example, while defining a search request and response messages in the same file .proto:
syntax = "proto3";
// SearchRequest 搜索请求
message SearchRequest { string query = 1; // 查询字符串 int32 page_number = 2; // 页码 int32 result_per_page = 3; // 每页条数 } // SearchResponse 搜索响应 message SearchResponse { ... }
add notes
.Proto add comments to files, supports C-style double slash //
single-line comments
Reserved field identifier
You can use reserved keywords specified reserved field and reserved identifiers:
message Foo {
reserved 2, 15, 9 to 11;
reserved "foo", "bar"; }
Note that you can not mix field names and identifiers in a reserved statement.
.proto file compiled results
When a protocol buffer compiler run .proto
time files, the compiler generates code for the selected language, for use in .proto
a message type definition file, service interface conventions and the like. Different generated code format different languages:
-
C ++: each
.proto
file to generate a.h
file and a.cc
file type of each message corresponding to a class -
Java: generating a
.java
file, each message corresponding to a same class, as well as a specialBuilder
class for creating a message interface -
Python: posture not the same for each
.proto
file type to generate a static message descriptor block containing the module with a metaclass metaclass create Python classes need to access data at runtime -
Go: generating a
.pb.go
file, each message type corresponds to a structure -
Ruby: generating a
.rb
file Ruby module comprising all message types -
JavaNano: similar to Java, but does not include the
Builder
class -
Objective-C: each
.proto
file to generate apbobjc.h
and apbobjc.m
document -
C #: generating a
.cs
file contains, for each message type corresponds to a class
More use of various languages refer to the official API documentation
type of data
Here direct reference to the official document described:
.proto | C++ | Java | Python | Go | Ruby | C# |
---|---|---|---|---|---|---|
double | double | double | float | float64 | Float | double |
float | float | float | float | float32 | Float | float |
int32 | int32 | int | int | int32 | Fixnum or Bignum | int |
int64 | int64 | long | ing/long[3] | int64 | Bignan | long |
uint32 | uint32 | int[1] | int/long[3] | uint32 | Fixnum or Bignum | uint |
uint64 | uint64 | long[1] | int/long[3] | uint64 | Bignan | ulong |
sint32 | int32 | int | intj | int32 | Fixnum or Bignum | int |
sint64 | int64 | long | int/long[3] | int64 | Bignan | long |
fixed32 | uint32 | int[1] | int | uint32 | Fixnum or Bignum | uint |
fixed64 | uint64 | long[1] | int/long[3] | uint64 | Bignan | ulong |
sfixed32 | int32 | int | int | int32 | Fixnum or Bignum | int |
sfixed64 | int64 | long | int/long[3] | int64 | Bignan | long |
bool | bool | boolean | boolean | bool | TrueClass / FalseClass | bool |
string | string | String | str / unicode [4] | string | String(UTF-8) | string |
bytes | string | ByteString | str | []byte | String(ASCII-8BIT) | ByteString |
These types of encoding rules about when serialized refer to the Protocol Buffer Encoding .
[1] java
[2] all
[3] 64
[4] Python
Defaults
-
String type defaults to an empty string
-
Default is null bytes byte type
-
Boolean Default false
-
The default value is 0 Value Type
-
enums type defaults to the first enumeration value defined, must be 0
Reference to specific acts of defaults in different languages generated code guide
Enumeration (Enum) TODO
Other Message
message SearchResponse {
repeated Result results = 1; } message Result { string url = 1; string title = 2; repeated string snippets = 3; }
message supports nested, as in another message type field
Import definition (Import)
You can use other types of import statement to import the description file declarations
import "others.proto";
protocol buffer compiler will -I / --proto_path
find the imported file in the directory specified, if the parameter is not specified, the default looks in the current directory.
Nested Message
message SearchResponse {
message Result { string url = 1; string title = 2; repeated string snippets = 3; } repeated Result results = 1; }
Message type names declared inside can only be used directly in internal references need to pre-parent message name on the outside, such as Parent.Type
:
message SomeOtherMessage {
SearchResponse.Result result = 1;
}
Support nested:
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 update TODO
Map Types
proto3 support map type declaration:
map<key_type, value_type> map_field = N;
message Project {...}
map<string, Project> projects = 1;
-
Button, built-in value types may be scalar type, or may be a custom message type
-
Field does not support
repeated
property -
Do not rely map type field order
Package (Packages)
In .proto
using the document package
declared package name, to avoid naming conflicts.
syntax = "proto3";
package foo.bar;
message Open {...}
Other message formats can be used in the definition of the package and name message name mode to type of use, such as:
message Foo {
...
foo.bar.Open open = 1;
...
}
In different languages, different effects package names generated after the definition of the compiled code:
-
In C ++: namespace corresponding to C ++, for example,
Open
be in the namespacefoo::bar
of -
In Java: package will be implemented as a Java package name unless you specify
option jave_package
options -
In Python: package is ignored
-
Go in: default package name as the package name unless you specify
option go_package
options -
JavaNano in: with Java
-
In C #: package will be converted to camel namespace, such as
Foo.Bar
, unless specifiedoption csharp_namespace
options
Define Service (Service)
If you want the message type is used RPC (Remote Method Invocation) system, you may .proto
define an RPC service interface file, protocol buffer compiler generates the service interface code depending on the selected language. For example, to define an RPC service and having a method that receives SearchRequest
and returns a SearchResponse
, in this case can be .proto
defined as follows file:
service SearchService {
rpc Search (SearchRequest) returns (SearchResponse) {} }
All interface methods generate interface code as the agreement of the client and the server, the server must implement defined, the client calls the same method on initiating direct request to the server. Comparison of egg pain is not required even if the business must also specify a parameter request message, typically define an empty message.
Options (Options)
When you define .proto file can mark a series of options. Options file does not change the meaning of the entire statement, but under certain circumstances can affect the processing mode. You can view the complete list of available options google/protobuf/descriptor.proto
.
Some of the options is the file level, meaning that it can act on the top-level scope is not included in any messages inside, enum or service definition. Some options are message-level, it can be used in the definition of inside information. Of course, some options can act in the field, enum type, enum values, type of service and service methods. But so far, no action can be an effective option in these types.
What are some common options:
-
java_package
(File option): Specifies the package to generate java classes where, if there is no clear statement java_package in .proto file, will use the default package name. When the code does not work does not need to generate java -
java_outer_classname
(File option): Specifies the name of the Java class generation, if not explicitly stated in java_outer_classname .proto file, the generated class name will be used camel naming .proto be generated based on the name of the file. The (foo_bar.proto generated java class named FooBar.java), has no effect when the need to generate java code -
objc_class_prefix
(File option): Specifies the Objective-C class prefix, will be before all classes and pre-enumeration type name. There is no default value, you should use 3-5 capital letters. Note that all two-letter prefix is reserved for Apple.
Basic specification
Description files .proto
as file suffix, statements except structure defined by a semicolon
-
Structure definition includes: message, service, enum
-
The method defined semicolon at the end of optional rpc
Message named using the naming hump, field names in lower case letters underlined spaced manner
message SongServerRequest {
required string song_name = 1; }
Enums type names using camel named, field name in uppercase and underlined separate ways
enum Foo {
FIRST_VALUE = 1;
SECOND_VALUE = 2; }
Service and uniform application of the method name rpc named Camel
Detailed results of the Go language compiler TODO
golang message corresponding to the struct, the compiler generates code that go, is converted to a field name Camel
Compile
Defined by .proto
generating Java, Python, C ++, Go , Ruby, JavaNano, Objective-C, or C # code file, you need to install the compiler protoc
. Reference Github project google / protobuf installation .Go language compiler will need to install a special plug-: golang / protobuf .
Run the command:
protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --java_out=DST_DIR --python_out=DST_DIR --go_out=DST_DIR --ruby_out=DST_DIR --javanano_out=DST_DIR --objc_out=DST_DIR --csharp_out=DST_DIR path/to/file.proto
Only reference here is like, the compiler examples of specific language, please refer to the detailed documentation, which, Go language use posture will explain in detail in other sections:
Tucao: shining the official document step by step is not guaranteed Oh!
More
-
Any message type
-
Oneof field
-
Custom Options
These usages are rarely used in practice, not described in detail here, especially custom design options for advanced usage, the need to refer to the official documentation .
当需要定义一个消息类型的时候,可能想为一个字段指定某“预定义值序列”中的一个值。例如,假设要为每一个SearchRequest消息添加一个 corpus字段,而corpus的值可能是UNIVERSAL,WEB,IMAGES,LOCAL,NEWS,PRODUCTS或VIDEO中的一个。 其实可以很容易地实现这一点:通过向消息定义中添加一个枚举(enum)就可以了。一个enum类型的字段只能用指定的常量集中的一个值作为其值(如果尝 试指定不同的值,解析器就会把它当作一个未知的字段来对待)。在下面的例子中,在消息格式中添加了一个叫做Corpus的枚举类型——它含有所有可能的值 ——以及一个类型为Corpus的字段:
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;
}
如果给枚举常量定义别名, 需要设置allow_alias option 为 true, 否则 protocol编译器会产生错误信息。
enum EnumAllowingAlias {
option allow_alias = true;
UNKNOWN = 0;
STARTED = 1;
RUNNING = 1;
}
enum EnumNotAllowingAlias {
UNKNOWN = 0;
STARTED = 1;
// RUNNING = 1; // Uncommenting this line will cause a compile error inside Google and a warning message outside.
}
枚举常量必须在32位整型值的范围内。因为enum值是使用可变编码方式的,对负数不够高效,因此不推荐在enum中使用负数。如上例所示,可以在 一个消息定义的内部或外部定义枚举——这些枚举可以在.proto文件中的任何消息定义里重用。当然也可以在一个消息中声明一个枚举类型,而在另一个不同 的消息中使用它——采用MessageType.EnumType的语法格式。
当对一个使用了枚举的.proto文件运行protocol buffer编译器的时候,生成的代码中将有一个对应的enum(对Java或C++来说),或者一个特殊的EnumDescriptor类(对 Python来说),它被用来在运行时生成的类中创建一系列的整型值符号常量(symbolic constants)。