Go 1.24 的 omitzero 是近年来 Go 语言生态系统中一个非常棒的更新。几周前,Go 1.24 Tools发布了,这是多年来生态系统中最棒的补充之一。之后,一些评论者提醒我,Go 1.24 版本中还有一个重要的新功能 omitzero,我意识到我在发布说明中漏掉了它。
忽略 JSON 中的可选字段 omitempty(Go 1.24 之前)
当你有一个结构体需要转换成 JSON 时,可能会有一些可选的字段。
例如,我们来看以下结构体:
type Response struct { |
假设 UpdatedAt 只有在数据库中的记录被更新后才应该设置。
考虑到这一点,如果字段有值,我们可能只想在 JSON 响应中返回该字段的值。
如果我们使用上述结构体并编组数据(UpdatedAt 为零值):
func main() { |
这会导致出现不需要的 updated_at JSON 字段:
j
{ |
从 Go 1.23(及之前版本)开始,实现可选 updated_at 的最佳方法是使用指针和 omitempty JSON 结构标签:
type Response struct { |
这允许你不指定 UpdatedAt,导致其零值(nil),该零值将通过结构标签 omitempty 被视为缺失,因此不会被编组:
{ |
这种方法工作得很好,但可能有点不方便,因为你现在必须使用指针。
对于那些认识我的人来说,我是 oapi-codegen 的共同维护者,你会明白,如何在 Go 中最好地处理 JSON 是我非常关心的问题。多年来,我们尝试了各种方法来简化用户体验,但都没有达到目标。
忽略 JSON 中的可选字段 omitzero(从 Go 1.24 开始)
然而,从 Go 1.24 开始,我们现在有了 JSON 结构标签 omitzero,它允许我们使用类型的实际零值作为不被编组的指示。
这使我们能够使用以下结构定义:
type Response_omitzero struct { |
请注意,我们现在可以使用非指针类型,这改进了我们与类型的交互方式,并且它按预期进行编组:
{ |
这为什么这么棒呢?
如上所述,一个关键点是减少处理大量额外指针。尽管在这个虚构的例子中只有一个指针,但当使用可选字段嵌套结构时,这可能会变得非常尴尬:
type Response struct { |
这会使一次性初始化结构变得更加困难,因为你无法获取指向常量值的指针来设置 Age: &30。
return Response{ |
当使用这样的代码时,这可能会有点麻烦,并且会变得相当重复,所以如果你可以避免使用指针繁重的类型,那就太棒了!
正如 omitzero 的提案中所述,这也具有更清晰的语义,因为 struct{} 可以称为“空”,但根据 omitempty 不会被视为“空”。