Protocol buffers _field()方法与protobuf中的默认值有什么关系?

Protocol buffers _field()方法与protobuf中的默认值有什么关系?,protocol-buffers,Protocol Buffers,我试图确定默认值和has_foo()方法之间的关系,这些方法在各种编程接口中声明。特别是,我试图确定在什么情况下(如果有的话)可以“区分”显式设置为默认值的字段和未设置的值 如果我显式地将一个字段(例如“Bar.foo”)设置为其默认值(例如零),那么对于该数据结构,Bar::有没有保证返回true?(对于C++生成的代码,从快速检查看来,这是正确的,但这并不意味着它是有保证的)。如果这是真的,那么可以区分显式设置的默认值和序列化之前的未设置。。 如果我显式地将一个字段设置为其默认值(例如,零)

我试图确定默认值has_foo()方法之间的关系,这些方法在各种编程接口中声明。特别是,我试图确定在什么情况下(如果有的话)可以“区分”显式设置为默认值的字段和未设置的值

  • 如果我显式地将一个字段(例如“Bar.foo”)设置为其默认值(例如零),那么对于该数据结构,Bar::有没有保证返回true?(对于C++生成的代码,从快速检查看来,这是正确的,但这并不意味着它是有保证的)。如果这是真的,那么可以区分显式设置的默认值和序列化之前的未设置。

  • 如果我显式地将一个字段设置为其默认值(例如,零),然后序列化该对象并通过线路发送它,那么该值是否会被发送?如果不是,则很明显,任何接收此对象的代码都无法区分显式设置的默认值和未设置的值。也就是说,序列化后将无法区分这两种情况——Bar::has_foo()在这两种情况下都将返回false


  • 如果无法区分差异,那么如果我想编码一个“可为null”的可选值,建议使用什么技术来编码protobuf字段?我想到了两个选项,但两个选项都不太好:(A)添加一个额外的布尔字段来记录字段是否设置,或者(b)使用一个“重复”字段,即使我在语义上想要一个可选字段——这样我就可以区分无值(长度为零的列表)和设置值(长度为一的列表)之间的区别.

    以下内容适用于“proto2”语法,而不是“proto3”:

    设置或不设置字段的概念是Protobuf的核心特性。如果将字段设置为值(任意值),则相应的
    has_xxx
    方法必须返回true,否则API中会出现错误

    如果未设置字段然后序列化消息,则不会为该字段发送任何值。接收方将解析消息,发现包含哪些值,并设置相应的“has_xxx”值

    此处详细说明了如何以wire格式实现此功能:。简短的版本是,消息被编码为键值对序列,并且只有显式设置的字段才包含在编码的消息中


    默认值仅在您尝试读取未设置字段时起作用。

    谢谢。但要明确的是:(1)如果我显式地将一个字段设置为一个值(甚至是它的默认值),那么has_xxx是真的;(2)如果我序列化一个protobuf对象,那么如果has_xxx为true,即使该字段的值是默认值,也会通过线路发送一个字段?我认为这不正确。它没有在您链接的规范文档中指出:(1)如果某个成员的值与默认值匹配,则无论如何都应该对其进行编码。(2) protobuf实现必须允许您区分编码的默认值和解码期间设置的默认值。当另一端的定义已经具有合适的默认值时,通过导线发送空标记+id需要额外的字节。此外,文档甚至指出“如果您的任何元素都是可选的,那么编码的消息可能有也可能没有带有该标记号的键值对。”proto2和proto3之间的行为发生了变化。根据proto3,不再有单独的“存在”概念。当且仅当字段不等于其默认值时,才会在导线上发送字段。(例外是消息类型的字段,它仍然遵循proto2行为。)@KentonVarda所以
    has_field
    现在本质上是
    是否等于\u default
    ?@TobiAkinyemi抱歉,我不完全知道。我创建了proto2,但我从未使用过proto3,只听过一些东西。我建议查看生成的代码,看看它是怎么说的。