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

Protocol buffers 协议缓冲区-唯一编号标签-澄清?,protocol-buffers,Protocol Buffers,我正在使用协议缓冲区,一切正常。除了我不明白的事实-为什么我需要proto文件中的编号标签: message SearchRequest { required string query = 1; optional int32 page_number = 2; optional int32 result_per_page = 3; } 当然,我读过: 如您所见,消息定义中的每个字段都有一个唯一的 编号标签。这些标记用于标识字段中的字段 消息二进制格式,并且不应在您的消息 类型正在使用

我正在使用协议缓冲区,一切正常。除了我不明白的事实-为什么我需要
proto
文件中的编号标签:

message SearchRequest {
  required string query = 1;
  optional int32 page_number = 2;
  optional int32 result_per_page = 3;
}
当然,我读过:

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

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

原型定义中的编号字段避免了版本的需要 检查哪一项是明确说明的 协议缓冲区的设计与实现。作为开发者 文件指出,该协议的设计部分是为了避免“丑陋” 代码“用于检查协议版本,如下所示:

问题

只是我还是完全不清楚

让我用另一种方式问:

如果我有一个类似上述文件的原型文件,然后我将其更改为:

message SearchRequest {
  required string query = 3; //reversed order
  optional int32 page_number = 2;
  optional int32 result_per_page = 1;
}
它在乎什么?我重新编译并添加了这个文件(我在上周做了多次)


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

在序列化和反序列化数据时,编号的标签用于匹配字段

显然,如果更改编号方案,并将此更改应用于序列化程序和反序列化程序,则不会出现问题

但是,请考虑,如果使用第一个编号方案保存数据,并使用第二个编号方案加载数据,则它会尝试将
查询
加载到
结果每页
,反序列化可能会失败

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

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

因为您显式地给它一个数字,所以反序列化程序仍然能够加载使用旧编号方案序列化的数据,而忽略对不存在的数据的反序列化。

protobuf在编码和解码时使用这些字段号。有关更多详细信息,请参阅

所以每个字段都有导线类型,所以int32的导线类型为0,字段号为2,所以它将被编码为0001 0000,即十六进制的10


后来当它被解码时,它左移了1,这使它成为001 0000,最后三个lsb决定了导线类型,也就是说,它然后决定了它的类型int字段,其余的决定了它是proto中的哪个字段,也就是说,00010是2。因此,导线类型为0(int)

的字段2现在已被理解。“他们很难举例说明吗?”罗伊纳米尔解释得很清楚。见我的帖子样本below@almasshaikh在这种情况下,一个简短的(15行!)并不能以一种简单的方式来解释它——这迫使我深入到内部——我觉得这很令人不安。@RoyiNamir,我认为这种想法因人而异。它总是冗长而不是简短,所以你永远不会得到反问题或让读者感到困惑。所以nvm;)@BorisMitioglov字段号并不表示字节偏移量,如果这是您的意思,它们只是任意标识符,但您编写的其他所有内容都是正确的。在二进制格式中,您需要一些系统来了解每段数据代表什么,而不像JSON那样在消息中序列化字段名称。
它关心什么
在我看来,您在这里提出了一个很好的观点。如果您真的不需要向后兼容,那么必须显式地声明数字是毫无意义的。它们可以(对于我的小型内部项目来说,应该)自动生成。
message SearchRequest {
  required string query = 1;
  optional int32 page_number = 2;
  optional int32 result_per_page = 3;
  optional int32 new_data = 4;
}