我用的是协议缓冲区,一切都很好。不过,我不明白为什么我需要proto文件中的编号标记:
message SearchRequest {
required string query = 1;
optional int32 page_number = 2;
optional int32 result_per_page = 3;
}当然,我读过文档:
如您所见,消息定义中的每个字段都有一个唯一的编号标记。这些标记用于标识邮件二进制格式的字段,并且在使用消息类型后不应更改。
我不明白如果我改变它会有什么区别。(我将创建一个新的proto并编译它--那么为什么它会在意呢?)
另一条规定:
proto定义中有编号的字段避免了版本检查的需要,这是设计和实现协议缓冲区的明确动机之一。正如开发人员文档所述,该协议的设计部分是为了避免类似于检查协议版本的“丑陋代码”:
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;
}它在乎什么?我重新编译并添加了这个文件(在过去的一周里我已经多次这样做了)。
我错过了什么?你能为这个编号的标签提供一个人类的解释吗?
发布于 2014-11-09 08:32:52
编号标记用于在序列化和反序列化数据时匹配字段。
显然,如果您更改编号方案,并将此更改应用于序列化程序和反序列化程序,则没有问题。
但是,考虑一下,如果您使用第一个编号方案保存数据,并用第二个方案加载数据,它将尝试将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;
}由于您显式地给它一个数字,您的反序列化器仍然能够加载使用旧的编号方案序列化的数据,而忽略了不存在的数据的反序列化。
发布于 2014-11-09 08:33:03
这些字段号在编码和解码时由protobuf使用。有关更多详细信息,请参阅这里。
所以每个字段都有导线类型,所以int32的线型为0,而您的字段号是2,所以它将被编码为0001 0000,也就是十六进制中的10。
在解码后,其左移1,使其为001 0 0,最后三位lsb决定线型,即确定它的int型场,而rest则决定其原为00010为2。因此,0 (int)型线的场2。
https://stackoverflow.com/questions/26826421
复制相似问题