go语言中的零值

huotuijin · · 3081 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

go语言中的零值是变量没有做初始化时系统默认设置的值。
var b bool // bool型零值是false
var s string // string的零值是""
var a *int
var a []int
var a map[string] int
var a chan int
var a func(string) int
var a error // error是接口
// 以上六种类型零值常量都是nil
所有其他数值型的类型(包括complex64/128)零值都是0,可以用常量表达式代表数值0的任何形式表示出来。

对于以上各种类型都可以通过==条件判断是不是零值:
if <变量> == <零值表达式> {
}
但是类型不能混用,变量类型和零值类型必须匹配。

结构也有零值。如果所有(递归的)字段都是零值,那么整个结构就是零值。但是没有零值常量用来表示某个结构的零值,所以也就无法用判断语句来识别一个结构是否处于零值。而且零值状态的结构也没有一个通用的语义,处于零值状态的结构可能意味着没有初始化,也可能是一个正常有用的状态。比如sync.Mutex零值状态就是处于没有锁住状态,是有意义的。所以不需要结构的零值常量。

数组和结构类似,有零值,但是没有相应的零值常量。

string的零值是"",也可以用len(x)==0 来判断零值字符串。但是用""更好一点,把len(x)==0留给slice用。

slice是个系统定义的结构,有三个字段:一个指针指到数据存储区,长度,存储区容量。只有三个字段都是零值的时候,这个变量才是零值。比如make([]int, 0, 0)创建的slice长度和容量都是0,但是指针不为空,所以不是零值。而且也没有办法直接设置slice所指向的指针,所以make出来的都不是零值。但是通常判断slice是不是空的时候是用len(x)==0,而不是用nil。用nil做判断容易混淆。如果函数返回值既可以是nil也可以是零长slice,那通常是不好的设计,但是调用者可以用len()==0做判断来避免问题。貌似go应该也可以设计成slice没有零值常量,只用len()==0来判断零长数组。这相当于一个结构没有零值常量,但是用一个方法来判断是不是初始化过了。

接口也是个系统定义的结构,有两个字段,都是指针。一个指向实现该接口的具体类型的数据,一个指向实现该接口的具体类型信息。两个字段都是nil的时候,这个变量才是nil。有一种情况是指向数据的指针是nil,指向类型的指针不是nil,这相当于this指针是空指针。此时在方法中访问数据的时候会segment fault,但是这种情况无法通过判断接口是nil识别出来。正常程序不应该出现这种只有数据是nil的情况。参考例子 https://tour.golang.org/methods/12

零值的map也有一定功能,可以在上面调用查询,但是无法添加数据。可以用于描述一个只读的空集。
var m map[string]int
a, ok := m["xxx"] // 任何nil值的map对于任何key,查到的结果是value的类型的零值,ok是false。

零值的chan也有用,发送数据到nil chan或者从nil chan接收数据都会造成死等,而close时会发生panic。参见例子 https://medium.com/justforfunc/why-are-there-nil-channels-in-go-9877cc0b2308

语言规范中说的零值:
https://golang.org/ref/spec#The_zero_value
When storage is allocated for a variable, either through a declaration or a call of new, or when a new value is created, either through a composite literal or a call of make, and no explicit initialization is provided, the variable or value is given a default value. Each element of such a variable or value is set to the zero value for its type: false for booleans, 0 for numeric types, "" for strings, and nil for pointers, functions, interfaces, slices, channels, and maps. This initialization is done recursively, so for instance each element of an array of structs will have its fields zeroed if no value is specified.


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:huotuijin

查看原文:go语言中的零值

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:701969077

3081 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传