关于go:Go-零值和空值的判断问题

35次阅读

共计 2331 个字符,预计需要花费 6 分钟才能阅读完成。

大家好,我是煎鱼。

前段时间分享了《Go 将减少内置的零值标识符 zero!》的新预约义标识符 zero。对应的签名如下:

// zero is a predeclared identifier representing the zero value
// for array and struct types.
var zero Type

我原想着还是一个有一点点新扭转。不过综合大家意见来看,因为只是针对数组(array)和构造体(struct),许多同学示意这个是比拟鸡肋的。因为依然 无奈很好的解决 Go 零值和空值的辨认问题,大喜过望。

本文是对零值和空值判断现状进行梳理和分享。

疾速温习零值

根本类型

var a int
var b bool
var c string

func main() {fmt.Printf("%+v\n", a) // 0
    fmt.Printf("%+v\n", b) // false
    fmt.Printf("%+v\n", c) // ""
}

复合类型

var a []int
var b map[string]int
var c [7]int
var d *int
var g chan int
var p Person

type Person struct {
    Name string
    Age  int
}

func main() {fmt.Printf("%+v\n", a) // []
    fmt.Printf("%+v\n", b) // map[]
    fmt.Printf("%+v\n", c) // [0 0 0 0 0 0 0]
    fmt.Printf("%+v\n", d) // <nil>
    fmt.Printf("%+v\n", g) // <nil>
    fmt.Printf("%+v\n", p) // {Name: Age:0}
}

进行空值判断

在理论的 Go 业务利用中,咱们须要对数据的零值和空值进行辨别,以便于实现一些空值的业务逻辑解决。

常见的有两种做法。如下:

  1. 在变量申明时,应用指针来解决,将其申明为指针类型。
  2. 在定义变量缺省值时,错开类型的零值。例如:int 零值是 0,业务里字段缺省值定义为 1 和 2 等。

第一种是用的最多的,也是前文评论区大家有所提到的。对于根底类型,具体的代码示例如下:

var a *int
var b *bool
var c *string

func main() {
    if a == nil {fmt.Print("煎鱼")
    }
    if b == nil {fmt.Print("进")
    }
    if c == nil {fmt.Print("脑子了")
    }
}

输入后果:煎鱼进脑子了。

对于复合类型,也是一样的:

var a []int
var b map[string]int
var g chan int

var c *[7]int
var d *int
var p *Person

对于复合类型的一些值类型,因为零值有可能是程序赋的值,也有可能是真空值。因而同样须要加上指针,用于辨认。

在 Go 业务程序上,大家为了解决这个零值和空值的判断问题。会采取相似的形式去编写包和程序。

如下代码:

type Person struct {
    Name *string
    Age  *int
}

func main() {
    s := `{"name": "煎鱼"}`

    var p Person
    err := json.Unmarshal([]byte(s), &p)
    if err != nil {fmt.Println(err)
    }
    fmt.Printf("p: %+v\n", p)
    fmt.Println(*p.Name)
}

输入后果:

p: {Name:0xc00010c380 Age:<nil>}
煎鱼

能够看到所传入的 json 字符串并不蕴含 age 字段,因而其值为 nil。

如果是为空字符串:

s := `{"name": ""}`

解析后输入的后果为:

p: {Name:0xc000096380 Age:<nil>}

以此就能够实现空值和零值的无效辨别,不再为此判断懊恼太多。

但也引入了一个麻烦的点,就是在获取值时须要应用 *p.Name 的形式。如果心愿“屏蔽”这个用法,个别还会再做一次函数封装作为 Getter 的办法。

新增 zero 解决什么问题

显然我再回去看行将新退出的 zero 标识符时,会发现他可能胜利 Go 的机缘是对零值的比拟判断,而并非空值的起因。

zero 应用场景是:

if val == zero(MyType) {}

又或是:

func example[T any]() T {
  // do something that returns an error...
  if err != nil {return zero(T)
  }
  //...
}

这么一梳理,发现的确和咱们设想中的有肯定的差距。因为咱们在理论的零值和空值的判断中,更须要的是对外部字段的数值判断例如:构造体里的某些字段,比拟少是只对构造体自身做空值判断。

总结

明天依据大家热议的反馈,从新梳理了 Go 中零值和空值的现状和判断技巧。感觉本次 zero 的退出,真的是只增强了构造体和数组类型自身的零值判断,而没有针对空值的好伎俩。

综合来看,思考到标准(SPEC)中零值是官网的标准约定,扭转的可能性也很低了。个人感觉外围团队新增判断形式或优化的可能性比拟低。

大家平时除了应用指针和预约义非零值的枚举值外,还会用什么办法来判断零值和空值呢,也欢送大家分享你的认识!

文章继续更新,能够微信搜【脑子进煎鱼了】浏览,本文 GitHub github.com/eddycjy/blog 已收录,学习 Go 语言能够看 Go 学习地图和路线,欢送 Star 催更。

Go 图书系列

  • Go 语言入门系列:初探 Go 我的项目实战
  • Go 语言编程之旅:深刻用 Go 做我的项目
  • Go 语言设计哲学:理解 Go 的为什么和设计思考
  • Go 语言进阶之旅:进一步深刻 Go 源码

举荐浏览

  • 又有新性能!Go 将有生成新模板的 gonew 工具链
  • Go1.21 那些事:泛型库、for 语义变更、对立 log/slog、WASI 等新个性,你晓得多少?
  • 互联网大厂裁员的起因和预兆 - 互联网大厂裁员的起因和预兆

正文完
 0