前言

按照Go语言规范,任何类型在未初始化时都对应一个零值:

布尔类型是false,整型是0,字符串是””

而指针、函数、interface、slice、c**hannel和map的零值都是nil**

nil Go中是一个预先声明的标识符

您可以在nil不声明的情况下使用它。

nil 可以表示多种类型的零值

在Go中,nil可以表示以下类型的零值:
  • pointer types (including type-unsafe ones).
  • map types.
  • slice types.
  • function types.
  • channel types.
  • interface types.
  1. package main
  2. import "fmt"
  3. type Person struct {
  4. Id int
  5. Name string
  6. Info interface{}
  7. }
  8. func main() {
  9. var p Person
  10. fmt.Println(p)// {0 <nil>}
  11. }

nil 使用场景

pointers

nil pointer
  • 指向 nil, 又名 nothing
  • pointer 的零值
  1. var p *int // 声明一个 int 类型的指针
  2. println(p) // <nil>
  3. p == nil // true
  4. *p // panic: runtime error: invalid memory address or nil pointer dereference
指针表示指向内存的地址,如果对 nil 的指针进行解引用的话就会导致 panic。那么为 nil 的指针有什么用呢? 先来看看一个计算二叉树和的例子:
  1. func (t *tree) Sum() int {
  2. if t == nil {
  3. return 0
  4. }
  5. return t.v + t.l.Sum() + t.r.Sum()
  6. }

slices

  1. // nil slices
  2. var s []T
  3. len(s) // 0
  4. cap(s) // 0
  5. for range s {
  6. } // iterates zero times
  7. s[i] // panic: index out of range
一个为nilslice,除了不能索引外,其他的操作都是可以的,slice有三个元素,分别是长度、容量、指向数组的指针,当你需要填充值的时候可以使用append函数,slice会自动进行扩充。所以我们并不需要担心slice的大小,使用append的话slice会自动扩容。
  1. var s []int
  2. for i := 0; i < 10; i++ {
  3. fmt.Printf("len: %2d cap: %2d\n", len(s), cap(s))
  4. s = append(s, i)
  5. }