Proto3:我可以向现有的原始字段添加“可选”吗?向后兼容吗?
为了让原始字段区分 0 和未设置,我想知道是否可以将其设为“可选”,或者是否需要弃用现有字段并创建一个新字段。所以:
message foo {
int32 bar = 0;
}
成为:
1)
message foo {
optional int32 bar = 0;
}
message foo {
int32 bar = 0 [deprecated = true];
optional int32 new_bar = 1
(1)如果向后兼容的话会更容易改变。
proto3 语言指南具有通用指南,但不涉及将普通 proto3(“隐式字段存在”)字段更改为可选字段。
在内部,普通字段和可选字段之间的编码不会改变。发生变化的是字段被编码的时间。让我们考虑旧原型(带有 normal 字段)和新原型(带有 Optional 字段)的不同情况:
旧的编码器原型,新的解码器原型,字段值非零:解码器获得正确的值,始终设置可选字段。
旧的编码器原型,新的解码器原型,字段值为零:解码器的行为就像可选字段未设置一样。
新的编码器原型,旧的解码器原型,字段未设置:解码器的行为就像字段值为零一样。
新的编码器原型,旧的解码器原型,字段集:解码器获得正确的值。
因此,它并不完全兼容,因为零值可能会丢失或出现缺失字段。但对于许多实际情况来说,它可能是可行的。
在显式存在和不存在之间更改字段是对序列化值有线格式的二进制兼容更改。
此更改可能安全也可能不安全,取决于应用程序的语义。
来自: https://protobuf.dev/programming-guides/field_presence/#considerations-for-change-compatibility,其中包含一个示例。
简而言之,唯一不同的行为发生在时:具有旧无存在字段(无
optional
关键字)的客户端A将默认字段值发送到具有新显式存在字段的客户端B(有 optional
关键字)。这里的客户端 B 将获得正确的字段值,但 has_xx()
方法将返回 false
。