nil切片与空切片不等价:nil切片底层指针为nil,s == nil为true;空切片(如[]int{}或make([]int,0))指针非nil,s == nil恒为false,尽管二者len和cap均为0。

nil 切片和空切片在 Go 中不等价,s == nil 的结果取决于底层指针是否为 nil,而不是看 len(s) 或 cap(s) 是否为 0。
怎么判断一个 slice 是 nil 还是 empty
核心看底层指针:nil 切片的 array 字段为 nil,而空切片的 array 指向一个合法地址(哪怕长度容量都是 0)。
-
var s []int→s == nil为true -
s := []int{}或s := make([]int, 0)→s == nil恒为false - 所有情况中
len(s)和cap(s)都返回0,不能靠它们区分
为什么 interface{} 会让 nil 切片“变非 nil”
接口值由 type 和 value 两部分组成;只要 value 字段被赋值(哪怕是一个全零的切片头),接口整体就不等于 nil。
-
var s []int; var i interface{} = s→i == nil为false,因为i.value已填充(内容是{array: nil, len: 0, cap: 0}) - 这导致常见误判:
if i == nil不会进分支,即使原始s是nil - 正确做法是先类型断言再判空:
if v, ok := i.([]int); ok && v == nil
append、len、cap 在两者上的行为一致吗
是的,内置函数对 nil 切片和空切片的行为完全相同,Go 运行时做了统一处理。
-
append(s, 1)对两者都正常扩容并返回新切片 -
len(s)、cap(s)、copy(dst, s)、for range s全部无差别工作 - 但
reflect.ValueOf(s).IsNil()可以区分:对nil切片返回true,空切片返回false
真正容易被忽略的是跨接口传递后的判空逻辑——它不反映原始切片状态,只反映接口值是否被赋值。别依赖 == nil 做业务分支,尤其当切片经过函数参数或 map value 传递后。


















