在 Go 语言中,如果对值为 nil 的 slice 和 map 执行读取、写入、删除或遍历操作,分别会产生怎样的行为?请给出具体说明。
考察说明
考查对 Go 中 nil slice 与 nil map 底层结构及其操作行为的掌握程度。
回答思路
- 【回答框架 1】nil slice 的底层是 slice 结构体,其 Data 指针为 nil,Len 和 Cap 均为 0。对 nil slice 进行 append 操作会分配新的底层数组并返回新的 slice,不会 panic;对 nil slice 进行索引访问或修改会引发 panic,因为数组越界。
- 【回答框架 2】nil map 的底层是 map 结构体,其指向实际哈希表的指针为 nil。对 nil map 进行读取(如 v := m[key])会返回零值,不会 panic;但向 nil map 写入键值对会引发 panic,因为无法分配存储空间。删除 nil map 中的键(delete(m, key))是安全的,不会 panic。
- 【回答框架 3】对 nil slice 或 nil map 进行 range 遍历都是合法的,循环体不会执行,因为它们的长度均为 0。使用 len() 和 cap() 函数获取 nil slice 的值均为 0,len(nil map) 也为 0。
- 【回答框架 4】需要注意的是,nil slice 与空 slice(如 make([]T, 0))的区别:两者 Len 和 Cap 都可能为 0,但空 slice 底层有非 nil 的数组指针(通常指向 zerobase)。在某些序列化场景中,nil slice 会被序列化为 null,而空 slice 会被序列化为空数组,因此需要根据需求选择合适的类型。
- 【关键点 1】对 nil slice 进行 append 是安全的,会分配新数组。
- 【关键点 2】对 nil map 进行读取和删除是安全的,但写入会 panic。
- 【关键点 3】range 遍历 nil slice 和 nil map 都是安全的,因为长度为 0。
- 【关键点 4】nil slice 与空 slice 在序列化时表现不同,应区分使用。
- 【易错点 1】误认为 append nil slice 会修改原 slice,实际需要接收返回值。
- 【易错点 2】误认为对 nil map 赋值会像 nil slice 一样自动分配,实际会 panic。
- 【易错点 3】忽略 nil slice 和空 slice 在 JSON 序列化中分别为 null 和 [] 的差异,可能导致数据不一致。