前言
当分配内存来存储一个类型的值时,它会被赋予该类型的默认值。 所以在 golang
中当通过声明或 new
出来的变量都会分配存储空间,而这些没有显式初始化都会给它一个默认值,而这个默认值就是零值。
零值
所有类型的零值如下:
- Boolean:false
- Integer:0
- Float:0.0
- String:“”
接口、切片、通道、映射、指针和函数:无
对于数组或者 struct
,如果未指定值,则数组或结构的元素将其字段归零。
type Person struct {
name string
age int
next *Person
}
fmt.Println([2]Person{})
// 输出结果:{"" 0 <nil>} {"" 0 <nil>
那么零值在我们项目中发挥着什么样的作用呢?
Slice 零值
切片 slice
的零值为 nil
,因此我们可以使用它来检查切片是否为空。
var s []int
if s == nil {
fmt.Println("slice is empty")
}
但需要注意,长度为零的 Slice
值与零Slice
不同。nil
的长度为零,但是使用make([]T, 0)
创建的切片的长度为零但不是 nil
。
var s1 []int // s1 是 nil
var s2 = []int{} // s2 不是nil ,而是长度为0的 Slice
var s3 = make([]int,0) //s3 不是nil ,而是长度为0的 Slice
如果Slice
的值是nil
正准备使用,所以无需检查是否是nil
sync.Mutex 零值
sync.Mutex
包含两个未导出的整数字段。 多亏了零值,只要声明了 sync.Mutex
,这些字段就会被设置为 0
。
type Counter struct {
mu sync.Mutex
count int
}
func (c *Counter) Inc() {
c.mu.Lock()
defer c.mu.Unlock()
c.count++
}
func main() {
var c Counter
c.Inc()
fmt.Println(c.Value())
}
从功能的角度来看,互斥锁的零值是解锁的。 所以,我们可以使用互斥锁的零值来创建一个新的计数器。
这是一个方便的属性。 这意味着我们可以创建一个互斥体并开始使用它,而不必担心它是否被锁定。byte.Buffer
零值bytes.Buffer
的零值是一个可以使用的空缓冲区,因此我们可以使用它来累积数据,然后将其读出。
var b bytes.Buffer
b.Write([]byte("Hello"))
b.Write([]byte(" "))
b.Write([]byte("World"))
fmt.Println(b.String()) // 将会输出结果 Hello World
sync.WaitGroup 零值
WaitGroup
的零值是有效的WaitGroup
。 我们可以直接使用它来做并发任务而不用初始化它。
var wg sync.WaitGroup // 声明的 WaitGroup 值是零值
for i:= 1; i<=10; i++ {
wg.Add(1)
go func(i int){
defer wg.Done()
fmt.Println("No: ", i)
}(i)
}
wg.Wait()
指针零值
指针的零值是 nil
。您对于具有nil
值的类型上调用方法时,对nil
进行判断返回默认值。
type Person struct {
Name string
sex int
}
func (p *Person) isBoy() bool {
if p == nil {
return false
}
return p.sex==2
}