Protocol Buffer学习教程之语法手册(二)

1.说明此向导介绍如何使用protocol buffer language创建一个自己的protocolbuffer文件,包括语法与如何通过“.proto”文件生成数据访问的类,此处只介绍proto2,proto3的更多消息点这里。这是一个参考指南,一步一步功能描述的示例,请访问以下链接,并选择你自己熟悉的开发语言。2.定义消息类型首先我们来看一个简单的示例,定义一个searchr
摘要由CSDN通过智能技术生成


1.说明

此向导介绍如何使用protocol buffer language创建一个自己的protocolbuffer文件,包括语法与如何通过“.proto”文件生成数据访问的类,此处只介绍proto2proto3的更多消息点这里

这是一个参考指南,一步一步功能描述的示例,请访问以下链接,并选择你自己熟悉的开发语言

2.定义消息类型

首先我们来看一个简单的示例,定义一个searchrequest消息格式,每一个search request有一个query字符串,页码,每页结果数量。以下是定义的“.proto”文件:

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

消息指定了三“段”(“名-值”对),每一段,有修饰符、类型、名称、编号组成,还会有一些可选项组成,如指定缺省值呀,后续章节中会介绍到。

段类型

在以上的示例中,所有的段都指定了类型。你也可以用复合类型,包括枚举与其他消息类型(protobuffer 定义的类型)

分配标记

从以上示例中可以看到,每一段都指定了唯一编号“= x”,它用于二进制格式中标记“段”,当你的消息类型投入使用后,它们的顺序不能改变。编码时编号在1~15区间内的编号占用一个字节,在16~2047区间用两个字节,所以,你可以保留1~15的编号给那些比较常用的元素使用,并为将来可能要增加的段预留一些此区间的编号。

最小编号为1,最大编号为229 - 1,或者536,870,911,但是19000 ~ 19999区间的编号是保留给Protocol Buffers使用的。

修饰符

required: 一个格式完好的消息必须最少有一个这种类型的段。被这种修饰符修饰的段,是必须赋值的,否则会被认为“未初始化”,如果未赋值,在debug版本序列化时会抛出断言错误,release版本能顺利通过,但是反序列化(解析)时,必然会失败的。除此之外,requiredoptional修饰类型就没有什么区别了。

optional: 一个格式完好的消息有N(N0)个这种类型的段。对于此字段的赋值,不是必须的。如果没有赋值,它将使用默认值,对于缺省数据类型,你可以指定默认值,如伪代码中的phone number,如果没有指定默认值,将使用系统默认值,数字类型为0string为空,bool型为false。对于嵌套类型,默认值为“默认实例”或“原型”。

repeated: 字段会出现N(0)次,重复的值将按顺序保存在“protocol buffer”中,你只要把它当成一个动态数组即可。

由于历史原因,repeated修饰的段的数据类型如果是数字类型的话,不能高效编码,为提高效果可以使用一个选项[packed=true]来获得更高的效率,示例如:

repeated int32samples = 4 [packed=true];

关于packed参见这里

Required 是永久的,使用此种修饰符时,要特别小心,当你不想给此种类型的字段赋值的话,你需要把它改成Optional类型,它可能会出现一些问题----接受方可能会认为此消息是非完事的,而拒绝解析。有些google开发者认为required利大于弊,所以他们更喜欢使用optionalrepeated。当然,这种观点不一定是普遍的。

定义多个消息

可以在一个“.proto”文件定义多个消息,特别是对那些有相互关联的消息,比较适用。如你需要给以上示例的请求消息加一个响应消息

message SearchRequest {
  
  required string query = 1;
  optional int32 page_number = 2;
  optional int32 result_per_page = 3;
}
 
message SearchResponse {
  
 ...
}

关于注释

.proto”文件注释,使用的是C/C++语法“//”,如下:

message SearchRequest {
  
  required string query = 1;
  optional int32 page_number = 2;// Which page number do we want?
  optional int32 result_per_page = 3;
// Number of results to return per page.
}

保留段

如果你要对以前定义的消息中的段删除,或者注释。将来使用者可能会更新他们的消息,并重新使用这些段,或者他们又使用此消息的旧版本,这将导致数据损坏,隐性错误等问题,有一个办法可以避免这些问题。把这个删除的段指定为reserved类型,可以通过它的标志指定,也可以通过名称(JSON版本会有问题)指定,指定后使用都如果再使用这些段,将会收到错误提醒。使用reserved时,同一行,不能混合使用标志与名称。

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

.proto生成的内容

通过protocol buffer 编译器对.proto文件进行编译后,能生成你选择的语言的代码。你可以通过此代码对你在.proto文件中描述的数据进行提取、给段赋值、把你打包后的数据序列化成流、把接收到的流反序列化成类实例等操作。

C++:对应每一个.proto文件生成.h.cpp文件。每个消息将生成一个类。可以通过此链接,找到对应语言的API

3.数据类型

以下列表中是.proto文件中数据类型与相应的语言之间的数据类型的对应关系。

.proto Type

Notes

C++ Type

Java Type

Python Type[2]

Go Type

double

double

double

float

*float64

float

float

float

float

*float32

int32

Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.

int32

int

int

*int32

int64

Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.

int64

long

int/long[3]

*int64

uint32

Uses variable-length encoding.

uint32

int[1]

int/long[3]

*uint32

uint64

Uses variable-length encoding.

uint64

long[1]

int/long[3]

*uint64

sint32

Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.

int32

int

int

*int32

sint64

Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.

int64

long

int/long[3]

*int64

fixed32

Always four bytes. More efficient than uint32 if values are often greater than 228.

uint32

int[1]

int

*uint32

fixed64

Always eight bytes. More efficient than uint64 if values are often greater than 256.

uint64

long[1]

int/long[3]

*uint64

sfixed32

Always four bytes.

int32

int

int

*int32

sfixed64

Always eight bytes.

int64

long

int/long[3]

*int64

bool

bool

boolean

bool

*bool

string

A string must always contain UTF-8 encoded or 7-bit ASCII text.

string

String

str/unicode[4]

*string

bytes

May contain any arbitrary sequence of bytes.

string

ByteString

str

[]byte

关于以上数据类型的编码方式的详情,点击这里

[1]Java, unsigned 32-bit and64-bit被解释成有符合整形,最高位被描述成符号位。

[2]对段进行赋值时,会执行类型检查。

[3]64-bit orunsigned 32-bit 整形被在解析时都被解析成long型,可以为int型,如果在设置的时候设置成int型的话。总之,值必须与设置的时候一致。参见[2]

[4]Pythonstrings将解析为宽字符,同时可以是ASCIIÿ

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MingoJ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值