阅读Google Protocol Buffers 指南,整理pb语法

官方网站:

https://developers.google.com/protocol-buffers/docs/proto3

1、简单定义一个Message 类型

pb语法文件以"*.proto"为文件扩展名。在版本proto3文件头需要包含版本类型“syntax = "proto3";”,缺省情况为proto2类型。

官方示例:

syntax = "proto3";

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

message为类标识符

SearchRequest为类名

string/int32为字段类型

query/page_number/result_per_page为字段名称

1/2/3为编号标签,用于序列化后内容标识,序号1~15需要1个字节,16~2047需要2个字节,最小编号为1,最大编号229-1或536870911。19000~19999系统预留,不可用。

 

2、字段描述规则

字段的规则主要分为单数和复数,用于描述字段是否是单个字段还是数组。默认情况下字段定义都是单数“singular”,如果需要定义数组需要在字段类型前面加“repeated”。

 

3、添加注释

 可以在字段定义结束后加“//”注释,该注释会在生成的字段代码中。
官方示例:

message SearchRequest {

  string query = 1; 

  int32 page_number = 2;  // Which page number do we want?  

 int32 result_per_page = 3;  // Number of results to return per page.

}

 

4、保留字段

编号定义后,无法更改,如果需要重新定义类型或删除旧的类型,需要在序列化文件中占位原定义的类型。这样才能保证更改后数据正常反序列化,并对以前数据兼容。否则数据格式不正确后,将导致对更改前的数据反序列化出错。

官方示例:

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

 

 

5、字段类型

.proto TypeNotesC++ TypeJava TypePython Type[2]Go TypeRuby TypeC# TypePHP Type
double doubledoublefloatfloat64Floatdoublefloat
float floatfloatfloatfloat32Floatfloatfloat
int32Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.int32intintint32Fixnum or Bignum (as required)intinteger
int64Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.int64longint/long[3]int64Bignumlonginteger/string[5]
uint32Uses variable-length encoding.uint32int[1]int/long[3]uint32Fixnum or Bignum (as required)uintinteger
uint64Uses variable-length encoding.uint64long[1]int/long[3]uint64Bignumulonginteger/string[5]
sint32Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.int32intintint32Fixnum or Bignum (as required)intinteger
sint64Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.int64longint/long[3]int64Bignumlonginteger/string[5]
fixed32Always four bytes. More efficient than uint32 if values are often greater than 228.uint32int[1]intuint32Fixnum or Bignum (as required)uintinteger
fixed64Always eight bytes. More efficient than uint64 if values are often greater than 256.uint64long[1]int/long[3]uint64Bignumulonginteger/string[5]
sfixed32Always four bytes.int32intintint32Fixnum or Bignum (as required)intinteger
sfixed64Always eight bytes.int64longint/long[3]int64Bignumlonginteger/string[5]
bool boolbooleanboolboolTrueClass/FalseClassboolboolean
stringA string must always contain UTF-8 encoded or 7-bit ASCII text.stringStringstr/unicode[4]stringString (UTF-8)stringstring
bytesMay contain any arbitrary sequence of bytes.stringByteStringstr[]byteString (ASCII-8BIT)ByteStringstring

 

  • string, 默认值为空字符串.
  • bytes, 默认值为空字节数组.
  • bool, 默认值为false.
  • 数值类型, 默认值为0.
  • enums, 从0开始的枚举.
  • message对象列, 没有设置默认值,根据不同语言给定相应的规则
  • int32,uint32,int64,uint64、bool和枚举是兼容的,可以相互转换,更改字段类型后,可以向前和向后兼容,但会强制类型转化,会截断数值,如64变32位,以前的数据会只被读取32位值。
  • sint32和sint64彼此兼容,fixed32与sfixed32彼此兼容。

6、枚举类型的定义

官方示例:

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;
}

enum为枚举关键字

enum类型必须定义枚举值0.

一般情况下不允许同值枚举存在。如果需要增加同值枚举需要添加“option allow_alias = true;”

官方示例:

enum EnumAllowingAlias {
  option allow_alias = true;
  UNKNOWN = 0;
  STARTED = 1;
  RUNNING = 1;
}

7、引用其他文件

官方示例:

import "myproject/other_protos.proto";

在多次引用过程中也可以控制引用的作用域。加关键字“public”将可以被下下次引用使用。

官方示例:

    // 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";
   old 引用了public new和other,other只能在old里面使用。
   
// client.proto
import "old.proto";
// You use definitions from old.proto and new.proto, but not other.proto

client引用了old,因为new在old引用中是public 的,所以client是可以使用new. 但不能使用other.

7、嵌套类型

message 可以嵌套多层message.
message 可以嵌套 enum.
官方示例:
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;
    }
  }
}

8、Any类型

PB支持未知类型。该类型包含任意序列化的消息作为字节,以及一个充当全局唯一标识符并解析为该消息类型的URL。要使用Any类型,您需要导入google / protobuf / any.proto。
官方示例:
import "google/protobuf/any.proto";

message ErrorStatus {
  string message = 1;
  repeated google.protobuf.Any details = 2;
}


9、Oneof类型
如果有一个包含多个字段的消息,并且最多可以同时设置一个字段,则可以通过使用该功能强制执行此行为并节省内存。
Oneof字段就像常规字段,除了一个共享内存中的所有字段,最多可以同时设置一个字段。 设置任何成员自动清除所有其他成员。 可以根据选择的语言检查使用case()或WhereOneof()方法设置一个值中的值。
官方示例:
message SampleMessage {
  oneof test_oneof {
    string name = 4;
    SubMessage sub_message = 9;
  }
}


10、Map类型
语法规则为:
map<key_type, value_type> map_field = N;

示例:
map<string, Project> projects = 3;

11、包Package
我们可以在“.proto”文件中定义包,可以防止类的名称冲突,在我们使用过程可以加包名来定义字段类型。
官方示例:
package foo.bar;
message Open { ... }

使用时,
message Foo {
  ...
  foo.bar.Open open = 1;
  ...
}


 

转载于:https://www.cnblogs.com/hobinly/p/7207778.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值