Nil in Go

发布于 作者: Ethan

引言

原本是一段时间前看的Go开发者大会(不记得是哪一年)的演讲,关于各类型nil的作用,现在忘了,复习一下。

nil

不同类型的nil属于不同类型,不能直接比较(编译报错)。

Pointer

指针的nil表示不指向任何内存地址。

  1. 作为初始变量。
  2. 判断是否有效。
  3. 函数返回值。

Slice

nil表示底层的数组指针为nillencap都为0。

  1. 初始化。
  2. 区分未初始化空切片与已初始化空切片。
  3. 函数返回值。

Map

表示未初始化(未分配内存)。

  1. 初始状态。
  2. 判断是否已初始化。nil map写入会panic,读取会返回该类型零值。
  3. 函数返回值。

Channel

表示未初始化(未分配内存)。

  1. 初始状态。
  2. 控制阻塞:发送和接收操作会永久阻塞,closepanic
  3. select过滤无效分支:如果selectchannil,则永远无法被选中。

Func

表示未绑定任何函数

  1. 初始状态。
  2. 判断函数是否已赋值。
  3. 回调函数默认值。

Interface

接口由两个部分组成:

// $GOROOT/src/runtime/runtime2.gotype 
iface struct {    
    tab  *itab       // 类型信息指针    
    data unsafe.Pointer // 实际数据指针
}
  • 类型信息 (tab):描述接口存储的具体类型及其方法集
  • 数据指针 (data):指向实际存储的值

一个接口为nil当且仅当:

tab == nil && data == nil

e.g.

var p *int = nil
var i interface{} = p // i 的类型是 *int,值是 nil
fmt.Println(i == nil) // 输出:false(因为类型部分非 nil)
  1. 接口初始状态。
  2. 表示“无有效值”,譬如error接口,为nil时表示成功。