我正在使用协议缓冲区,一切正常。除了我不理解的事实 - 为什么我需要proto
文件中的编号标签:
message SearchRequest {
required string query = 1;
optional int32 page_number = 2;
optional int32 result_per_page = 3;
}
当然,我已经阅读了docs:
如您所见,消息定义中的每个字段都具有唯一性 编号标签。这些标签用于标识您的字段 消息二进制格式,一旦消息不应更改 类型正在使用中。
我不明白如果我改变它会有什么不同。 (我将创建一个新的原型并编译它 - 所以它为什么关心?)
原型定义中的编号字段消除了对版本的需求 检查哪些是明确说明的动机之一 协议缓冲区的设计和实现。作为开发人员 文档说明,协议的设计部分是为了避免“丑陋” 代码“像这样检查协议版本:
if (version == 3) {
...
} else if (version > 4) {
if (version == 5) {
...
}
...
}
问题
只是我还是完全不清楚?
让我以不同的方式提出这个问题:
如果我有一个类似上述文件的proto文件,那么我将其更改为:
message SearchRequest {
required string query = 3; //reversed order
optional int32 page_number = 2;
optional int32 result_per_page = 1;
}
它在乎什么?我重新编译并添加文件(我在上周已多次完成)。
我错过了什么?你能为这个编号的标签提供人对人的解释吗?答案 0 :(得分:23)
编号标签用于在序列化和反序列化数据时匹配字段。
显然,如果更改编号方案,并将此更改应用于序列化器和反序列化器,则没有问题。
但请注意,如果您使用第一个编号方案保存数据,并使用第二个编号方案加载它,则会尝试将query
加载到result_per_page
,反序列化可能会失败。
现在,为什么这有用? 我们假设您需要在数据中添加另一个字段,很久就会使用该模式:
message SearchRequest {
required string query = 1;
optional int32 page_number = 2;
optional int32 result_per_page = 3;
optional int32 new_data = 4;
}
因为您明确地给它一个数字,所以您的反序列化程序仍然能够加载使用旧编号方案序列化的数据,而忽略了对不存在的数据进行反序列化。
答案 1 :(得分:3)
这些字段编号在编码和解码时由protobuf使用。有关详细信息,请参阅here。
因此每个字段都有线型,因此int32的线型为0,字段编号为2,因此它将被编码为0001 0000,即十进制为10。
稍后当它被解码时,它的左移1,这使得它成为001 0000,最后三个lsb决定导线类型,即它然后输出int类型的字段,其余决定原型中的哪个字段即00010是2.因此,电线类型0(int)的字段2