首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >协议缓冲区-唯一编号标签-澄清?

协议缓冲区-唯一编号标签-澄清?
EN

Stack Overflow用户
提问于 2014-11-09 08:25:48
回答 2查看 15K关注 0票数 56

我用的是协议缓冲区,一切都很好。不过,我不明白为什么我需要proto文件中的编号标记:

代码语言:javascript
运行
复制
message SearchRequest {
  required string query = 1;
  optional int32 page_number = 2;
  optional int32 result_per_page = 3;
}

当然,我读过文档

如您所见,消息定义中的每个字段都有一个唯一的编号标记。这些标记用于标识邮件二进制格式的字段,并且在使用消息类型后不应更改。

我不明白如果我改变它会有什么区别。(我将创建一个新的proto并编译它--那么为什么它会在意呢?)

另一条规定:

proto定义中有编号的字段避免了版本检查的需要,这是设计和实现协议缓冲区的明确动机之一。正如开发人员文档所述,该协议的设计部分是为了避免类似于检查协议版本的“丑陋代码”:

代码语言:javascript
运行
复制
if (version == 3) {
  ...
} else if (version > 4) {
  if (version == 5) {
    ...
  }
  ...
}

问题

只是我还是完全不清楚?

让我用另一种方式来问:

如果我有一个像上面的文件一样的proto文件,然后我将它更改为:

代码语言:javascript
运行
复制
message SearchRequest {
  required string query = 3; //reversed order
  optional int32 page_number = 2;
  optional int32 result_per_page = 1;
}

它在乎什么?我重新编译并添加了这个文件(在过去的一周里我已经多次这样做了)。

我错过了什么?你能为这个编号的标签提供一个人类的解释吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-11-09 08:32:52

编号标记用于在序列化和反序列化数据时匹配字段。

显然,如果您更改编号方案,并将此更改应用于序列化程序和反序列化程序,则没有问题。

但是,考虑一下,如果您使用第一个编号方案保存数据,并用第二个方案加载数据,它将尝试将query加载到result_per_page中,反序列化可能会失败。

现在,为什么这个有用?假设您需要在模式已经使用很久之后向数据中添加另一个字段:

代码语言:javascript
运行
复制
message SearchRequest {
  required string query = 1;
  optional int32 page_number = 2;
  optional int32 result_per_page = 3;
  optional int32 new_data = 4;
}

由于您显式地给它一个数字,您的反序列化器仍然能够加载使用旧的编号方案序列化的数据,而忽略了不存在的数据的反序列化。

票数 56
EN

Stack Overflow用户

发布于 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。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26826421

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档