Golang Go语言中Protobuf3 关于区分默认值和缺失值问题

发布于 1周前 作者 itying888 来自 Go语言

Golang Go语言中Protobuf3 关于区分默认值和缺失值问题

要上 gRPC 啦,由于 gRPC 要用 pb3,而 pb3 里面废除了 required 和 optional,所有字段都是 optional 了。我们面临如何判断某个字段是没值,还是默认值 0 的问题。

知乎上有个方法: https://zhuanlan.zhihu.com/p/46603988

也找到了 fieldmask 的方法: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/field_mask.proto

Stack Overflow 上也有增加 null 字段做法: https://stackoverflow.com/questions/42622015/how-to-define-an-optional-field-in-protobuf-3

不知道哪种更好,前提是,pb 的序列化性不能退化,毕竟从 json 换 pb 就是为了它的序列化性能。 有没有踩过坑的同学来讨论一下。


更多关于Golang Go语言中Protobuf3 关于区分默认值和缺失值问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

14 回复

正在 pb+rRpc 和 thrift 的坑中爬行,还挂着 zookeeper …………

更多关于Golang Go语言中Protobuf3 关于区分默认值和缺失值问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你可以用 proto2,就算 google 内部主流仍然是用 proto2

grpc 根本不关心你用什么序列化协议

用 repeated fields,然后判断长度

G 家推荐用 pb3 作为 gRPC 的 IDL,貌似 pb2 也能用,不过既然 G 家推荐 pb3,估计以后就不支持 pb2 了,为了避免为以后留坑,还是用 pb3 吧。

这能有什么坑,2 和 3 的在二进制协议层面上根本没有区别,2 显然更适合描述接口设计

前端表示被这个坑惨了

我说的坑是,哪天 gRPC 的 codegen 不支持用 pb2 来做 IDL 了

你们前端现在用 grpc-web ?如果不用 gRPC 框架的话,也没必要换 pb3 了哇

protoc 的 “自举” 是在 pb2 上的,在可预见的未来 pb2 回像 py2 一样存在…

如果用 grpc 的同时还用 protobuf 给 http api 的话,不推荐 wrapper 的方式。

我们目前大部分情况没有特别大的对 null 和默认值区分的需求,偶尔遇到一般这样:
所有 enum 的 0 都表示未设置
不得不需要区分的地方用 boolean 加 hasXXX

在Go语言中处理Protobuf3时,区分默认值和缺失值是一个常见的需求。Protobuf3 引入了一些特性来处理这种情况,尤其是通过 oneof 和可选字段(optional fields,在 Protobuf3.15+ 中重新引入)的支持。

  1. 可选字段(Optional Fields)

    • 在 Protobuf3.15 及更高版本中,你可以通过声明字段为 optional 来明确表示该字段是可选的。这样,在生成的 Go 代码中,你可以检查字段是否被设置。如果字段未被设置,它将返回一个特殊的零值(例如,对于整数是0,对于字符串是空字符串),但你可以通过某种方式(如使用指针或特定的封装类型)来区分这个零值是默认值还是因字段未设置而产生的。
  2. 使用默认值

    • 如果字段未被声明为 optional,则当字段未被设置时,它将采用在 Protobuf 定义中指定的默认值。在 Go 中,这通常意味着字段将具有其类型的零值。要区分这种情况和显式设置为零值的情况,你可能需要在应用逻辑中引入额外的上下文或标记。
  3. 处理技巧

    • 在设计 Protobuf 消息时,考虑使用 oneof 来表示一组互斥字段,这有助于在语义上区分字段的存在与否。
    • 在 Go 代码中,可以通过封装类型(如使用指针或自定义类型)来显式表示字段的缺失状态。

总之,通过合理利用 Protobuf3 的新特性(如可选字段)和 Go 代码中的封装技术,你可以有效地区分默认值和缺失值。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!