Protocol Buffers
Table of Contents
- 2 spaces, 80 characters per line,
lower_snake_case.proto
- If a file is in
my/package/
, then the package name should bemy.package
Code Example #
syntax = "proto3";
package test;
import "myproject/other.proto";
enum Foo {
// The zero value enum should have the suffix UNSPECIFIED.
FOO_UNSPECIFIED = 0;
FOO_FIRST_VALUE = 1;
FOO_SECOND_VALUE = 2;
}
message SongServerRequest {
required string song_name = 1;
repeated string keys = 1;
}
service SearchService {
rpc Search (SearchRequest) returns (SearchResponse);
}
Compilation #
# Protocol Buffers
protoc --proto_path=IMPORT_PATH --go_out=DST_DIR path/to/file.proto
# Protocol Buffers with gRPC
protoc --proto_path=IMPORT_PATH --go_out=plugins=grpc:DST_DIR path/to/file.proto
--proto_path
- for resolvingimport
directives (default is current directory) In general you should set the--proto_path
flag to the root of your project and use fully qualified names for all imports.
Message #
- every field has an unique number, don’t change any of the existing numbers
- 1 - 15 stored in 1 byte - frequently occurring message elements
- 16 - 2047 stored in 2 bytes
- reserved 19000 through 19999
Fields #
- singular - default, zero or one times
repeated
- field repeated any number of times, order is perserved, use pluralized name- previously deleted/commented fields can be reused, can be prohibited by
reserved
field - use
song_name1
instead ofsong_name_1
message Foo {
reserved 2, 15, 9 to 11;
reserved "foo", "bar";
}
Scalar Types #
.proto | Go | Notes |
---|---|---|
double | float64 | |
float | float32 | |
int32 | int32 | variable-length encoding, inefficient for negative numbers |
int64 | int64 | variable-length encoding, inefficient for negative numbers |
uint32 | uint32 | variable-length encoding |
uint64 | uint64 | variable-length encoding |
sint32 | int32 | variable-length encoding, signed |
sint64 | int64 | variable-length encoding, signed |
fixed32 | uint32 | 4 bytes, efficient for numbers greater than 228 |
fixed64 | uint64 | 8 bytes, efficient for numbers greater than 256 |
sfixed32 | int32 | 4 bytes |
sfixed64 | int64 | 8 bytes |
bool | bool | |
string | string | UTF-8 or ASCII, cannot be longer than 232 |
bytes | []byte | sequence of bytes no longer than 232 |
Enums #
- every enum definition must contain a constant that maps to zero as its first element
- range of positive 32-bit integer
- can use
reserved
field
enum Foo {
reserved 2, 15, 9 to 11, 40 to max;
reserved "FOO", "BAR";
}
Imports #
// 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
Any #
- lets you use messages as embedded types without having their definition
- serialized as
bytes
- along with a URL that acts as a globally unique identifier for and resolves to that message’s type
- can be used by importing
google/protobuf/any.proto
import "google/protobuf/any.proto";
message ErrorStatus {
string message = 1;
repeated google.protobuf.Any details = 2;
}
Oneof #
- like union in C
- fields cannot be
repeated
- oneof cannot be
repeated
message SampleMessage {
oneof test_oneof {
string name = 4;
SubMessage sub_message = 9;
}
}
Map #
key_type
- integral or string type (no floats,bytes
or enums)value_type
- any type except another map- fields cannot be
repeated
map<key_type, value_type> map_field = N;