Protobuf中float字段改optional float在Go中使用是否可行及最优方案
问题1:修改后在Go语言中使用是否存在问题?
只要你的Protobuf工具链满足最低版本要求,本身不存在序列化/反序列化的兼容性问题,但需要注意业务代码的适配:
- 版本要求:需使用protoc 3.12及以上版本,Go Protobuf核心依赖
google.golang.org/protobuf需升级到v1.26.0及以上,配套的protoc-gen-go版本要和核心依赖版本匹配,才能正确生成optional字段对应的Go代码。 - 生成代码的差异:
原定义下baz字段在Go中会生成float32类型的变量,默认零值为0,无法区分「对方未传该字段」和「对方明确传了0值」两种场景;
加optional修饰后,baz字段会生成*float32类型的指针,值为nil代表对方未传该字段,指针指向的内容为实际传输的值,哪怕是0也能明确识别。 - 风险提示:如果你的原有业务代码直接对
baz做数值运算,修改定义后需要先判断指针是否为nil再取值,直接解引用空指针会触发panic。新旧服务/客户端互传消息时,wire格式完全兼容,不会出现解析失败的问题:旧版本发送的无baz字段的消息,新版本解析后baz为nil;新版本未赋值baz的消息发送给旧版本,旧版本会按Protobuf默认规则取0作为baz的值。
问题2:是否需要先废弃旧字段再新增新字段?
这个场景完全不需要这么操作。
你只是给原有字段加了optional修饰,字段号、字段类型、字段名都没有变化,前后的序列化格式完全兼容,废弃再新增字段反而会无端增加兼容成本,还会浪费字段号。只有当你需要修改字段的类型、字段号,或者调整字段的业务语义时,才需要走「标记旧字段为deprecated→新增新字段→全链路升级完成后删除旧字段」的流程。
内容的提问来源于stack exchange,提问作者srikantrao
相关产品推荐
相关产品推荐

