一个田地出现在电线上吗?移动一个字段_一个单一的字段是安全的吗
https://developers.google.com/protocol-buffers/protocol-buffers/docs/docs/proto3## Oneof 并没有明确地说Oneof
s不会出现在电线上(并且它的成员就像可选的字段一样),但它很大程度上暗示了它。
如果这是真的,那么似乎总是会总是是一个安全的向后兼容一个单一),但文档说:
将字段移入或移出一个:您可能会失去一些 消息是之后的信息(某些字段将被清除) 序列化和解析。但是,您可以安全地移动一个字段 进入一个新的Oneof,如果是 知道只有一个是设置的。
它没有区分两者。这只是监督吗?
它还没有提到是否可以安全地“嵌入” One Onef内部的字段并完全删除One One One One One One One One。
另外,如果一个Oneof包含多个原始字段,所有这些字段都是默认值,那么它如何知道设置哪个字段?
我可以在某个地方找到有关安全向后兼容Oneof
更改的更多详细信息吗?官方文件令人惊讶地缺乏
https://developers.google.com/protocol-buffers/docs/proto3#oneof doesn't explicitly say that oneof
s don't show up on the wire (and it's members are like optional fields), but it heavily hints at it.
If this is true, then it seems it would always be a safe backwards-compatible to move a field out of a oneof without anything getting cleared (unlike moving into a oneof), but the documentation says:
Move fields into or out of a oneof: You may lose some of your
information (some fields will be cleared) after the message is
serialized and parsed. However, you can safely move a single field
into a new oneof and may be able to move multiple fields if it is
known that only one is ever set.
It doesn't distinguish between the two. Is this just an oversight?
It also doesn't mention whether it's safe to "inline" the fields inside of a oneof and remove the oneof entirely.
Also, if a oneof contains multiple primitive fields, all of which are default value, how does it know which one is set?
Is there somewhere I can find more details about safe backwards-compatible oneof
changes? The official documentation is surprisingly lacking
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
就个人而言,我发现整个
向后兼容性
部分与泥浆一样清晰。我无法决定是在谈论标签重复使用问题< / code>时,是否是指移动 /删除是指编辑
.proto < / code < / code>,还是在一个中设置 /清除字段在程序中实例化对象。
第一部分(直接在标题下的para 向后兼容)是可以的。如果编辑了oneof 中删除
.proto
,请从field
,读取旧数据的新程序可能会遇到field> field 在该旧数据中。除了忽略
字段
外,无能为力,结果对象会说未设置
。A
标签
是字段号
和电线类型
的组合(请参见文档的这一部分)。因此,如果一个人在一个人的.proto
文件中编辑了Oneof
的内容,并将field>字段号重复使用,则可以完全不同的字段类型当选择旧数据时会令人困惑。旧数据可以包含包含相同
字段编号
但不同电线类型
的标签。移动字段
对于将字段移入/从一个
Oneof
中移动到/输出;在实例化对象的上下文中,这是有意义的。假设该对象是由于文件 /流 /其他任何内容的必要线数据而创建的。该对象很可能会设置其中一个字段。如果程序然后继续在该对象中设置另一个字段
,则原始字段将被清除(很可能是delete
)。但是,使用闪亮的新鲜分配的对象,默认情况下没有设定字段。因此,将一个字段移入其中不会删除 / nulth任何其他字段。我对“和 的解释,如果知道只有一个字段,则能够移动多个字段”是代表字段的对象可以处于“未设置”状态。因此,将字段的集合移至单个
Oneof
对象作品中,规定除一个“未设置”状态中的所有字段。也许“梅”是关于将其编译为C ++还是Java或C#或其他任何内容的“可能”,也许在字段的表示方式上存在语言差异,以及它们是否可以具有“未设置”状态。例如,c#支持nulls(例如,您可以具有可确定的int),但是C ++不可能。不过,这与向后兼容性有关,这对我来说尚不清楚。为了使其与向后兼容性有关,我们当然是在谈论编辑
.proto
文件,并与使用该程序的较旧的预编辑版本创建的数据进行新的ProGAM交易?然后,这将回到一个简单的问题,即字段号
是否在.proto
文件的历史上的任何时刻都没有重复使用。删除字段
我不知道他们在“删除一个单个字段并将其添加回去”中所产生了什么。如果他们可以展示自己想的步骤的顺序,那将是非常有帮助的。
抱歉,不要非常有帮助。 Oneof不会像明显的在这里电线上出现的所有内容都是设置的单个字段。
另外,如果一个Oneof包含多个原始字段,所有这些字段均为默认值,它如何知道设置哪一个?
请参阅 docs的这一部分和,尤其是此。注意访问者方法,该方法将确保对象的内部状态设置了哪个字段。其他支持无原始原语的Langaugs也可能会使用它。
Personally speaking, I find that whole
Backward Compatibility
section to be as clear as mud. I can't decide if, when it talks aboutTag Re-Use Issues
, whether moving / deleting is referring to editing the.proto
, or setting / clearing fields in an instantiated object in one's program.The first part (the para directly under the title Backward Compatibility) is OK. If a
.proto
is edited, removing afield
from theoneof
, the new program reading old data might encounter thatfield
in that old data. There's nothing it can do, except ignore thefield
and the resultant object will saynot set
.A
tag
is the combination of afield number
and awire type
(see this part of the docs). So if one edited the contents of aoneof
in one's.proto
file, and reused afield number
for a totally different field type, things could get confusing when deserialising old data. The old data could contain tags comprising of the samefield number
but differentwire type
.Moving Fields
As for moving fields into / out of a
oneof
; it makes sense in the context of an instantiated object. Suppose that object has been created as a result of deserialising wire data from a file / stream / whatever. That object will, most likely, have one of the fields set. If the program then goes on to set anotherfield
in that object, the original field is going to get cleared (which may well be adelete
). However, with a shiny new freshly allocated object, it contains no set fields by default. So, moving a field into it won't delete / null any other field.My interpretation of "and may be able to move multiple fields if it is known that only one is ever set" is that objects representing fields can be in a "not set" state. Thus moving a collection of fields into a single
oneof
object works provided that all except one are in this "not set" state. Perhaps the "may" is depenedent on whether this is compiled to C++ or Java or C# or whatever, perhaps there's language differences in how fields are represented and whether or not they can have a "not set" state. For example, C# supports nulls (e.g. you can have a nullable int), but C++ doesn't.Though, what this has to do with backward compatibility is not clear to me. For it to have anything to do with backward compatibility, surely we're talking about editing a
.proto
file and having a new progam deal with data created with an older pre-edit version of the program? That would then go back to a simple matter of whether or not afield number
has or has not been reused at any point in the history of the.proto
file.Deleting Fields
I don't know what they're getting at in "Delete a oneof field and add it back". It would be very helpful if they could show the order of the steps they're thinking of.
Sorry to not be very helpful. Oneofs do not show up on the wire as is evident here, so all that is going appear on the wire is the single field that is set.
Also, if a oneof contains multiple primitive fields, all of which are default value, how does it know which one is set?
See this part of the docs and especially this. Note the accessor methods, which will ensure that the object's internal state as to which field is set gets updated. Other langauges that support nullable primitives might use that too.