Go中零值与空值的实现与区别

作者:

文章目录
  • 变量声明但未显式初始化时,Go 自动赋的默认值。它保证“未初始化”也有确定、可用的值 TYPE ZERO VALUE Integer 0 Floating point 0.0 Boolean false String "" Pointer nil Interface nil Slice nil Map nil Array fields zero (每个元素都是其零值) Struct fields zero (每个元素都是其零值) Channel nil Function nil
  • 下面是一个完整的Go示例,展示了omitempty&omitzero标签在不同类型上的应用: TYPE ZERO VALUE EMPTY VALUE WITHOUT OMIT OMITEZERO OMITEMPTY Integer 0 0 0 OMIT OMIT Floating point 0 0 0 OMIT OMIT Boolean FALSE FALSE FALSE OMIT OMIT String "" "" "" OMIT OMIT Pointer nil nil null OMIT OMIT Interface nil nil null OMIT OMIT Slice nil nil null OMIT OMIT Slice nil make([]T, 0) [] [] OMIT Map nil nil null OMIT OMIT Map nil make(map[K]V, 0) {} {} OMIT Array: [0]T fields zero [0]T [] OMIT OMIT Array: [N]T fields zero ❌ [T] OMIT [T] Struct: struct{} fields zero ❌ {} OMIT {} Struct: struct{ F T } fields zero ❌ {"F": T} OMIT {"F": T} Channel nil nil ❌ ❌ ❌ Function nil nil ❌ ❌ ❌ 到此这篇关于Go中零值与空值的实现与区别的文章就介绍到这了,更多相关Go 零值 空值内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: Golang 零值、空值与空结构的使用小结 Go语言中的空值(nil)与零值(zerovalue)区别详解 浅析Go中关于零值和空值判断的问题 Go语言nil标识符(空值/零值)
  • 目录
    • 内置类型的零值/默认值
    • Json序列化中的omitempty&omitzero
      • omitempty
      • omitzero
    • 总结

      变量声明但未显式初始化时,Go 自动赋的默认值。它保证“未初始化”也有确定、可用的值

      TYPE ZERO VALUE
      Integer 0
      Floating point 0.0
      Boolean false
      String ""
      Pointer nil
      Interface nil
      Slice nil
      Map nil
      Array fields zero (每个元素都是其零值)
      Struct fields zero (每个元素都是其零值)
      Channel nil
      Function nil

      当对一个结构体的某个字段的tag设置为omitempty时,如果这个字段是空值(empty value,和零值不一样)时,那么这个字段就会在序列化时省略

      The “omitempty” option specifies that the field should be omitted from the encoding if the field has an empty value, defined as false, 0, a nil pointer, a nil interface value, and any empty array, slice, map, or string.

      omitempty标签的判断逻辑如下:

      • 对于布尔类型:false被视为空
      • 对于数值类型:0被视为空
      • 对于指针、接口:nil被视为空
      • 对于字符串:""(空字符串)被视为空
      • 对于数组、切片、map:长度为0被视为空,既包含未初始化的又包含空的

      对于空结构体、所有字段都为默认值的零值结构体、以及一些实际含义为零的结构体(例如time.Time{}),omitempty都无能为力,会进行输出。

      因此在Go 1.24之前想对某个结构体不输出,可选的一种方案是使用指针类型

      type VanillaStruct struct {
          StructTyp1 struct{}        // 空结构体
          StructTyp2 struct{ A int } // 零值结构体
          TimeTyp    time.Time       // 实际含义为零的结构体
      ​
          StructTyp3 *struct{}
          StructTyp4 *struct{ A int }
          TimeTyp2   *time.Time
      }
      ​
      type OmitemptyStruct struct {
          StructTyp1 struct{}        `json:",omitempty"`
          StructTyp2 struct{ A int } `json:",omitempty"`
          TimeTyp1   time.Time       `json:",omitempty"`
      ​
          StructTyp3 *struct{}        `json:",omitempty"`
          StructTyp4 *struct{ A int } `json:",omitempty"`
          TimeTyp2   *time.Time       `json:",omitempty"`
      }
      ​
      func main() {
          s1 := VanillaStruct{}
          ss1, err := json.Marshal(s1)
          fmt.Println(err, string(ss1)) 
          // {"StructTyp1":{},"StructTyp2":{"A":0},"TimeTyp":"0001-01-01T00:00:00Z","StructTyp3":null,"StructTyp4":null,"TimeTyp2":null}
      ​
          s2 := OmitemptyStruct{}
          ss2, err := json.Marshal(s2)
          fmt.Println(err, string(ss2)) 
          // {"StructTyp1":{},"StructTyp2":{"A":0},"TimeTyp1":"0001-01-01T00:00:00Z"}
      }
      

      Go 1.24 给 encoding/json 新增omitzero:按零值(zero value)省略

      在序列化时,omitzero选项指定如果字段值为零,则该结构体字段应被省略

      • 如果该类型定义了IsZero() bool方法,那么这个零值就通过IsZero方法来判断
      • 否则是根据字段是否是零值(通过reflect.Value.IsZero判断)来判断
      type VanillaStruct struct {
          StructTyp1 struct{}        // 空结构体
          StructTyp2 struct{ A int } // 零值结构体
          TimeTyp    time.Time       // 实际含义为零的结构体
      }
      ​
      type OmitzeroStruct struct {
          StructTyp1 struct{}        `json:",omitzero"`
          StructTyp2 struct{ A int } `json:",omitzero"`
          TimeTyp1   time.Time       `json:",omitzero"`
      }
      ​
      func main() {
          s1 := VanillaStruct{}
          ss1, err := json.Marshal(s1)
          fmt.Println(err, string(ss1))
          // {"StructTyp1":{},"StructTyp2":{"A":0},"TimeTyp":"0001-01-01T00:00:00Z"}
      ​
          s2 := OmitzeroStruct{}
          ss2, err := json.Marshal(s2)
          fmt.Println(err, string(ss2))
          // {}
      }
      

      下面是一个完整的Go示例,展示了omitempty&omitzero标签在不同类型上的应用:

      TYPE ZERO VALUE EMPTY VALUE WITHOUT OMIT OMITEZERO OMITEMPTY
      Integer 0 0 0 OMIT OMIT
      Floating point 0 0 0 OMIT OMIT
      Boolean FALSE FALSE FALSE OMIT OMIT
      String "" "" "" OMIT OMIT
      Pointer nil nil null OMIT OMIT
      Interface nil nil null OMIT OMIT
      Slice nil nil null OMIT OMIT
      Slice nil make([]T, 0) [] [] OMIT
      Map nil nil null OMIT OMIT
      Map nil make(map[K]V, 0) {} {} OMIT
      Array: [0]T fields zero [0]T [] OMIT OMIT
      Array: [N]T fields zero [T] OMIT [T]
      Struct: struct{} fields zero {} OMIT {}
      Struct: struct{ F T } fields zero {"F": T} OMIT {"F": T}
      Channel nil nil
      Function nil nil

      到此这篇关于Go中零值与空值的实现与区别的文章就介绍到这了,更多相关Go 零值 空值内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

      您可能感兴趣的文章:

      • Golang 零值、空值与空结构的使用小结
      • Go语言中的空值(nil)与零值(zerovalue)区别详解
      • 浅析Go中关于零值和空值判断的问题
      • Go语言nil标识符(空值/零值)

      站内搜索