nil 是 Go 语言中一个预先声明的标识符,用于表示指针、通道、函数、接口、映射或切片类型的零值。nil 不是关键字,而是一个预声明的标识符,可以在作用域内被重新定义(但不推荐)。
nil 的定义
从 Go 源码中可以看到 nil 的定义:
1 2 3 4 5 6 7 8
// nil is a predeclared identifier representing the zero value for a // pointer, channel, func, interface, map, or slice type. varnil Type // Type must be a pointer, channel, func, interface, map, or slice type
// Type is here for the purposes of documentation only. It is a stand-in // for any Go type, but represents the same type for any given function // invocation. type Type int
说明:
nil 是一个预先声明的标识符,表示指针、通道、函数、接口、映射或切片类型的零值
Type 是一个类型代理,表示全部类型,底层实现是 _type
nil 的类型
nil 本身没有固定的类型,它的类型取决于上下文。nil 可以用于以下类型:
指针类型(pointer)
通道类型(channel)
函数类型(func)
接口类型(interface)
映射类型(map)
切片类型(slice)
示例
1 2 3 4 5 6
var p *int = nil// 指针类型 var c chanint = nil// 通道类型 var f func() = nil// 函数类型 var i interface{} = nil// 接口类型 var m map[string]int = nil// 映射类型 var s []int = nil// 切片类型
nil 的使用场景
1. 指针的零值
1 2 3 4 5 6 7 8
var p *int if p == nil { fmt.Println("p is nil") }
// 使用前需要初始化 p = new(int) *p = 42
2. 切片的零值
1 2 3 4 5 6 7 8 9
var s []int if s == nil { fmt.Println("s is nil") }
var f func() if f == nil { fmt.Println("f is nil") }
// 不能调用 nil 函数 // f() // panic: call of nil function
// 使用前需要赋值 f = func() { fmt.Println("function called") } f()
6. 接口的零值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
var i interface{} if i == nil { fmt.Println("i is nil") }
// 接口的 nil 判断需要注意 var p *int = nil i = p if i == nil { // 这里不会执行,因为 i 的类型是 *int,值才是 nil fmt.Println("i is nil") } // 正确的判断方式 if i == nil || (reflect.ValueOf(i).Kind() == reflect.Ptr && reflect.ValueOf(i).IsNil()) { fmt.Println("i is nil or points to nil") }
nil 的比较
基本比较
1 2 3 4 5 6 7
var p *int = nil var s []int = nil var m map[string]int = nil