大家好,我是煎鱼。
大家学习和使用 Go 语言时,有一个神奇的概念:零值(zero-values)。零值这个名字是具体谁起的,又是从哪里先开始喊起的,已经难以考究了。
每次有新同学刚开始转语言,工程上总会提到这个,想要试图改变零值。又或是没考虑到,一旦程序用了 0 作为 default 值,又要兼容零值的问题。
今天给大家分享一个关于零值的新提案,目测已经八九不离十了(在发布此文时,该提案已被正式 accepted)。
图片
基础类型的例子如下:
func main() {
var i int
var f float64
var b bool
var s string
fmt.Printf("%v %v %v %q\n", i, f, b, s)
}
输出结果:
0 0 false ""
复合类型的例子如下:
type Person struct {
Name string
Age int
Weight float64
}
func main() {
var p Person
var m map[int]string
var s []string
fmt.Printf("%#v\n%#v\n%#v\n", p, m, s)
}
输出结果:
main.Person{Name:"", Age:0, Weight:0}
map[int]string(nil)
[]string(nil)
类型和零值的映射表格如下:
数据类型 |
零值 |
int, int8, int16, int32, int64 |
0 |
uint, uint8, uint16, uint32, uint64 |
0 |
uintptr |
0 |
float32, float64 |
0 |
byte |
0 |
rune |
0 |
string |
"" (empty string) |
complex64, complex128 |
(0,0i) |
arrays of non-nillable types |
array of zero-values |
arrays of nillable types |
array of nil-values |
事情的起因是:@Nathan Cormier 在社区提了吐槽和提案《proposal: builtin: zero function[1]》:
图片
他表示:Go 语言目前提供了几种获取类型零值的方法,如果能有一种统一的方法来实现这一点,代码的可读性会更高。
有同学深思,哪来的几种?其实可以:
var z MyType
return z
还可以:
return *new(MyType)
初始化结构体后出来的都是零值。
紧接着就会遇到开头提到的问题,你怎么知道这是零值,还是缺省值?难以直接判别。
更重要的是,这不太符合 Go 的设计哲学,又是多种途径,还和缺省值产生混淆。显然和主打工程的 Go 的发展路子不合。
这次经过一番撕扯,最终是由 Go 核心团队负责人 @Russ Cox 出来主持大局,提出了新提案并一路向前。
图片
Go 将会增加一个新的预定义标识符 zero,它是一个无类型的零值,适用于数组和结构体类型。
以下是 zero 的类型签名:
// zero is a predeclared identifier representing the zero value
// for array and struct types.
var zero Type
他不会像 nil 一样。我们可以对照看看 nil 的类型签名:
// nil is a predeclared identifier representing the zero value for a
// pointer, channel, func, interface, map, or slice type.
var nil Type // Type must be a pointer, channel, func, interface, map, or slice type
Nil 受限于 chan、func、interface、map、slice、pointer 等类型。
zero 的可赋值性规则如下:
可能会有的同学担心,zero 和短零(0, "", or nil)产生冲突。对此可以放心。在设计的规则上:zero 在短零有效的任何地方都无效,所以在使用上不会产生混淆。
实际问题上,解决了以下几点:
通用概念来讲:
会有同学认为,现有的 return _, _, err 会比 return zero, zero, err 更短并且感觉更好。(但在清晰程度上会不如 zero 和 nil)
也有同学会认为自己写一个这个实现也很简单,是否有必要为此专门增加一个 zero 预定义值?
可以用泛型如下实现:
func Zero[T any]() T {
var v T
return v
}
对此在很多提案上,都很容易陷入怪圈。有了泛型后,照实现来讲,什么都可以自己写一份。
也会有一派认为以后判断错误类型要变成:
if err != zero {
...
}
会非常奇怪。以后可能会出现 if err != nil 和 if err != zero 的奇怪代码场景。
注:这个场景是假定 zero 标识符能适用于所有的数据类型下才会出现。本次并不存在。
目前的社区讨论比较发散,认为 zero 标识符未来也可以取代所有的零值。但从提案内容和提交的 SPEC CL 来看,@Russ Cox 一直针对的是数组和结构体的零值场景去使用 zero 标识符。
这个提案已经进入到最终阶段,已经被正式接受,基本跑不了了。
图片
以后我们在不同类型下对零值判断,可以基于:
数据类型 |
使用什么作为零值 |
int 等数字类型 |
使用 0 |
string 字符串类型 |
使用 ”“(空字符串) |
slice, map, function, pointer, channel, and interface 等类型 |
使用 nil |
array 和 struct 类型 |
可使用 zero 标识符 |
虽然在使用上,做了一定的使用场景的切分,也就是只有数组和结构体类型使用 zero 标识符。但对于写 Go 用户而言,认知上是会存在明确混淆的。
以后你给其他同学解释零值,解释起得区分两种场景来介绍。我感觉还不如 zero 标识符一统零值天下。但很可惜,本次提案暂时并没有这个计划。
[1]proposal: builtin: zero function: https://github.com/golang/go/issues/60695
[2]cmp: add Or: https://github.com/golang/go/issues/60204#issuecomment-1550369151
当前名称:Go 将增加内置的零值标识符 zero!
网站路径:http://www.csdahua.cn/qtweb/news24/366624.html
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网