在 Go 语言中,空切片(empty slice)和 nil 切片(nil slice)分别指什么?它们之间有哪些关键区别?
考察说明
考察对 Go 切片底层表示和零值语义的理解
回答思路
- 【回答框架 1】切片在 Go 中是一个结构体,包含指向底层数组的指针、长度 len 和容量 cap。nil 切片是未初始化的切片,其底层指针为 nil,len 和 cap 均为 0,直接赋值给一个切片变量且未 make 时即为 nil 切片。
- 【回答框架 2】空切片是已初始化但长度为 0 的切片,可以通过 make([]T, 0) 或字面量 []T{} 创建,其底层指针可能指向一个零长度的数组,也可能为 nil(在某些实现中),但关键在于它有一个有效的切片头,且不为 nil。
- 【回答框架 3】两者的主要区别:nil 切片等于 nil,可以用 s == nil 判断,而空切片不等于 nil;对 nil 切片和空切片调用 len、cap 和 append 操作的结果在多数情况下相似(append 会分配新数组),但 nil 切片在 JSON 序列化时输出为 null,空切片输出为 [],这一差异影响 API 响应;此外,空切片是一个有效的切片,支持所有切片操作,而 nil 切片作为接收者时可能引发 panic(如果方法内部解引用)。
- 【回答框架 4】从底层看,nil 切片的内部表示是零值,而空切片通过 make 或字面量创建后通常有一个非 nil 的底层数组(即使长度为 0),因为 make 会分配内存;但空切片也可能是 nil 指针(例如 var s []int; s = append(s) 后),不过此时它已变成非 nil。实际使用时,应优先使用 nil 切片来表示“无”,用空切片来表示“零个元素”。
- 【关键点 1】nil 切片是零值,等于 nil,len 和 cap 均为 0。
- 【关键点 2】空切片是长度为 0 的可使用切片,不等于 nil。
- 【关键点 3】JSON 序列化时 nil 切片输出 null,空切片输出 []。
- 【易错点 1】不要用空切片或 nil 切片做相等比较(切片只能和 nil 比较)。
- 【易错点 2】对 nil 切片使用 range 是安全的,但直接索引访问会 panic。