Go 中的 nil 表示一个类型的零值,nil 不是关键字。

指针

如果一个方法的接收者类型是指针,即使这个对象的值是 nil,指针的方法也可以正常执行。

type person struct{}

func (p *person) Say() {
        fmt.Println("hello")
}

func (p person) Say1() {
        fmt.Println("hello1")
}

func main() {
        var p *person
        fmt.Println("p: ", p)
        p.Say() // hello
        p.Say1() // panic
}

Slice

一个为 nil 的 slice,除了不被索引,其他操作都是可以的。

Map

一个 nil 的 map,可以看成是一个只读的 map。如过进行写操作就会 panic。

Channel

var c chan int
<-c // block
c <- 1 // block
close(c) // panic

Interface

interface 不是一个指针,它的底层有两部分,一部分是类型,一部分是值。

type myerr struct{}

func (m *myerr) Error() string { return "" }

func getErr1() error {
        return nil
}

func getErr2() error {
        var err *myerr
        return err
}
func main() {
        err1 := getErr1()
        fmt.Println(err1 == nil) // true, error(nil, nil)
        err2 := getErr2()
        fmt.Println(err2 == nil) // false, error(*myerr, nil)
}

nil 的小特性

nil是无法比较的

“==” 对于 nil 来说是一种未定义的操作。

func main() {
    fmt.Println(nil==nil) // invalid operation: nil == nil (operator == not defined on nil)

}

空指针的地址都是一样的

空指针的地址都是0x0,无论类型是什么。

func main() {
        var m map[int]string
        var ptr *int
        fmt.Printf("%p", m) // 0x0
        fmt.Printf("%p", ptr) // 0x0
}

参考

理解Go语言的nil