Go语言omitempty选项的实现

 更新时间:2023年06月08日 09:13:35   作者:黎明⁢  
本文主要介绍了Go语言omitempty选项的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在使用Golang的时候,不免会使用Json和结构体的相互转换,这时候常用的就是 json.Marshal 和 json.Unmarshal 两个函数。这时候在定义json结构体的时候,我们会用到 omitempty 这个字段,这个字段作用就是 空值省略,看似简单,但是却有很多小坑,这篇文章带你稍微研究一下他的用途和功能。

omit:

v. 删除; 忽略; 漏掉; 遗漏; 不做; 未能做;

adj. 省略了的;省去的;

基本用法

当我们设置json的struct的时候,会定义每个字段对一个json的格式,比如定义一个dog 结构体:

type Dog struct {
    Name   string
    Weight int
}

现在我们对他进行初始化,将其编码为JSON格式:

func main() {
    d := Dog{
        Name:   "小黑",
        Weight: 20,
    }
    marshalDog, err := json.Marshal(d)
    if err != nil {
        fmt.Println(err.Error())
    }
    fmt.Println(string(marshalDog))
}

则输出的结果为:

{"Name":"小黑","Weight":20} 

现在假如有一个结构体变量我们没初始化,那么结果可能也会跟我们预期的不太一样:

d := Dog{
        Name: "小黑",
    }

输出的结果为:

{"Name":"小黑","Weight":0}

很明显,狗的weight是未知,而不是0,并不是我们想要的结果,我们更想要的结果是:

{"Name":"小黑"}

为了实现这样的目的,我们这时候应该使用 omitempty 选项来帮我们实现,当我们在Dog结构体加上这个tag的时候:

type Dog struct {
    Name   string
    Weight int `json:",omitempty"`
}

此时,输出结果为:

{"Name":"小黑"}

不能单纯使用omitempty

当结构体相互嵌套的时候,那么omitempty就可能出现问题,比如:

type Variety struct {
    Color    string
    Category string
}
type Dog struct {
    Name    string
    Weight  int     `json:",omitempty"`
    Variety Variety `json:",omitempty"`
}
func main() {
    d := Dog{
        Name: "小黑",
    }
    marshalDog, err := json.Marshal(d)
    if err != nil {
        fmt.Println(err.Error())
    }
    fmt.Println(string(marshalDog))
}

输出结果为:

{"Name":"小黑","Variety":{"Color":"","Category":""}}

omitempty 为什么对嵌套结构体不生效呢?这是因为GO只知道简单结构体例如int,string,pointer 这种类型的空值,不知道Variety类型的空值是什么,为了不显示我们没有提供值的自定义结构体,我们可以使用结构体指针:

type Dog struct {
    Name    string
    Weight  int      `json:",omitempty"`
    Variety *Variety `json:",omitempty"`
}

运行结果为:

{"Name":"小黑"}

但是如果给出下面情况的赋值:

d := Dog{
        Name:    "小黑",
        Variety: &Variety{Color: "black"},
    }

运行结果为:

{"Name":"小黑","Variety":{"Color":"black","Category":""}}

可以看到,omitempty只对*Variety生效。所以想要嵌套结构体里面的字段也能有空值省略的效果,就要在定义嵌套的结构体的时候,对里面的每个字段都要加上omitempty选项。如下所示:

type Variety struct {
    Color    string `json:",omitempty"`
    Category string `json:",omitempty"`
}

运行结果如下:

{"Name":"小黑","Variety":{"Color":"black"}}

剩下的最后一个坑就是:如果想要某个值就是为空(有实际意义),也就是说当一个空值有实际意义的时候就显示,没有实际意义(当时还不知道其值)的时候就不显示,这样的需求应该怎么做?如果还是向上面那样,当我们需要Category为空的时候(Category:“”),最后会发现omitempty选项会把这个空值字段省略。正确的做法是使用指针来定义其变量。最后代码如下:

package main
import (
    "encoding/json"
    "fmt"
)
type Variety struct {
    Color    *string `json:",omitempty"`
    Category *string `json:",omitempty"`//一定要是*string类型
}
type Dog struct {
    Name    string
    Weight  int      `json:",omitempty"`
    Variety *Variety `json:",omitempty"`
}
func main() {
    color := "black"
    //此处的空值有实际意义
    category := ""
    d := Dog{
        Name:    "小黑",
        Variety: &Variety{Color: &color, Category: &category},
    }
    marshalDog, err := json.Marshal(d)
    if err != nil {
        fmt.Println(err.Error())
    }
    fmt.Println(string(marshalDog))
}

运行结果如下:

{"Name":"小黑","Variety":{"Color":"black","Category":""}}

到此这篇关于Go语言omitempty选项的实现的文章就介绍到这了,更多相关Go语言omitempty选项内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 深入解析Go语言中上下文超时与子进程管理

    深入解析Go语言中上下文超时与子进程管理

    这篇文章小编将通过一个实际问题的案例,和大家深入探讨一下Go语言中的上下文超时和子进程管理,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-10-10
  • GoFrame glist 基础使用和自定义遍历

    GoFrame glist 基础使用和自定义遍历

    这篇文章主要为大家介绍了GoFrame glist的基础使用和自定义遍历示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • 利用golang实现pdf中自动换行的表格

    利用golang实现pdf中自动换行的表格

    这篇文章主要给大家介绍了如何利用golang实现pdf中自动换行的表格,文中通过代码示例给大家讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-02-02
  • Go for-range 的 value值地址每次都一样的原因解析

    Go for-range 的 value值地址每次都一样的原因解析

    循环语句是一种常用的控制结构,在 Go 语言中,除了 for 关键字以外,还有一个 range 关键字,可以使用 for-range 循环迭代数组、切片、字符串、map 和 channel 这些数据类型,这篇文章主要介绍了Go for-range 的 value值地址每次都一样的原因解析,需要的朋友可以参考下
    2023-05-05
  • Go语言实现Snowflake雪花算法

    Go语言实现Snowflake雪花算法

    雪花算法产生的背景当然是twitter高并发环境下对唯一ID生成的需求,得益于twitter内部牛的技术,雪花算法能够流传于至今并且被广泛使用,本文就详细的介绍一下,感兴趣的可以了解一下
    2021-06-06
  • Go语言实现聊天小工具的示例代码

    Go语言实现聊天小工具的示例代码

    这篇文章主要为大家详细介绍了如何利用Go语言实现聊天小工具,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • golang实现java uuid的序列化方法

    golang实现java uuid的序列化方法

    这篇文章主要介绍了golang实现java uuid的序列化方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • go如何终止多个for select循环嵌套的方法

    go如何终止多个for select循环嵌套的方法

    当您想从嵌套循环中中断,从select内部终止循环时,标记的中断非常有用,本文主要介绍了go如何终止多个for select循环嵌套的方法,具有一定的参考价值,感兴趣的可以了解一下
    2024-01-01
  • 谈谈对Golang IO读写的困惑

    谈谈对Golang IO读写的困惑

    这篇文章主要介绍了谈谈对Golang IO读写的困惑,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • golang中json小谈之字符串转浮点数的操作

    golang中json小谈之字符串转浮点数的操作

    这篇文章主要介绍了golang中json小谈之字符串转浮点数的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03

最新评论