Contents

Protobuf

Protobuf

gRPC推荐使用proto3,这里只介绍常用语法,按照官方文档的结构翻译,英文水平有限,复杂的部分果断放弃,更多高级使用姿势请参考官方文档

Message定义

一个message类型定义描述了一个请求或响应的消息格式,可以包含多种类型字段。

例如定义一个搜索请求的消息格式SearchRequest,每个请求包含查询字符串、页码、每页数目。每个字段声明以分号结尾。

syntax = "proto3";
message SearchRequest {
    string query = 1;
    int32  page_number = 2;
    int32  result_per_page = 3;
}

分配Tags

消息的定义中,每个字段都有一个唯一的数值标签。这些标签用于标识该字段在消息中的二进制格式,使用中的类型不应该随意改动。其中,[1-15]内的标识在编码时占用一个字节,包含标识和字段类型。[16-2047]之间的标识符占用2个字节。建议为频繁出现的消息元素分配[1-15]间的标签。如果考虑到以后可能或扩展频繁元素,可以预留一些。

最小的标识符可以从1开始,最大到229 - 1,或536,870,911。不可以使用[19000-19999]之间的标识符, Protobuf协议实现中预留了这些标识符。在.proto文件中使用这些预留标识号,编译时会报错。

字段规则

  • 单数形态:一个message内同名单数形态的字段不能超过一个
  • repeated:前置repeated关键词,声明该字段为数组类型
  • proto3不支持proto2中的requiredoptional关键字

添加注释

.proto文件中添加注释,支持C/C++风格双斜线//单行注释。

syntax = "proto3";              // 协议版本声明
// SearchRequest 搜索请求消息
message SearchRequest {
    string query = 1;           // 查询字符串
    int32  page_number = 2;     // 页码
    int32  result_per_page = 3; // 每页条数
}

保留字段名与Tag

可以使用reserved关键字指定保留字段名和标签。

message Foo {
    reserved 2, 15, 9 to 11;
    reserved "foo", "bar";
}

基本数据类型

.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 Bignum long
uint32 uint32 int[1] int/long[3] uint32 Fixnum or Bignum uint
uint64 uint64 long[1] int/long[3] uint64 Bignum ulong
sint32 int32 int intj int32 Fixnum or Bignum int
sint64 int64 long int/long[3] int64 Bignum long
fixed32 uint32 int[1] int uint32 Fixnum or Bignum uint
fixed64 uint64 long[1] int/long[3] uint64 Bignum ulong
sfixed32 int32 int int int32 Fixnum or Bignum int
sfixed64 int64 long int/long[3] int64 Bignum 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

Message嵌套

message SearchResponse {
    message Result {
        string url = 1;
        string title = 2;
        repeated string snippets = 3;
    }
    repeated Result results = 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;
        }
    }
}

Protobuf —> Go

proto中的message对应go中的struct,全部使用驼峰命名规则。嵌套定义的messageenum转换为go之后,名称变为Parent_Child结构。

// Test 测试
message Test {
    int32 age = 1;
    int64 count = 2;
    double money = 3;
    float score = 4;
    string name = 5;
    bool fat = 6;
    bytes char = 7;
    // Status 枚举状态
    enum Status {
        OK = 0;
        FAIL = 1;
    }
    Status status = 8;
    // Child 子结构
    message Child {
        string sex = 1;
    }
    Child child = 9;
    map<string, string> dict = 10;
}
// Status 枚举状态
type Test_Status int32
const (
    Test_OK   Test_Status = 0
    Test_FAIL Test_Status = 1
)
// Test 测试
type Test struct {
    Age    int32       `protobuf:"varint,1,opt,name=age" json:"age,omitempty"`
    Count  int64       `protobuf:"varint,2,opt,name=count" json:"count,omitempty"`
    Money  float64     `protobuf:"fixed64,3,opt,name=money" json:"money,omitempty"`
    Score  float32     `protobuf:"fixed32,4,opt,name=score" json:"score,omitempty"`
    Name   string      `protobuf:"bytes,5,opt,name=name" json:"name,omitempty"`
    Fat    bool        `protobuf:"varint,6,opt,name=fat" json:"fat,omitempty"`
    Char   []byte      `protobuf:"bytes,7,opt,name=char,proto3" json:"char,omitempty"`
    Status Test_Status `protobuf:"varint,8,opt,name=status,enum=test.Test_Status" json:"status,omitempty"`
    Child  *Test_Child `protobuf:"bytes,9,opt,name=child" json:"child,omitempty"`
    Dict   map[string]string `protobuf:"bytes,10,rep,name=dict" json:"dict,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
}
// Child 子结构
type Test_Child struct {
    Sex string `protobuf:"bytes,1,opt,name=sex" json:"sex,omitempty"`
}