不一定。同类型指针变量值均为 nil 时 == 比较结果为 true;但接口、切片、map、chan、func 或含指针的结构体因底层是多字段头结构,其 nil 的“相等性”可能失效。

Go 中两个 nil 指针用 == 比较一定为 true 吗?
不一定。同类型指针变量值都是 nil 时,== 比较结果确实是 true;但一旦涉及接口、切片、map、chan、func 或者包含指针的结构体,nil 的“相等性”就可能失效——因为它们底层不是单纯指针,而是有多个字段的头结构。
nil 指针比较安全的场景:纯指针类型
只有当你确认两边都是相同基础类型的指针(比如 *int、*string),且没经过接口包装或嵌套,== 才可靠。
-
nil指针本身是零值,所有同类型nil指针在内存中表现为全 0 字节,所以直接比较地址位是安全的 - 例如:
var a, b *int,之后a == b就是true,因为两者都未初始化 - 但注意:
var p *int; var i interface{} = p,此时i == nil是false,因为i包含了类型信息(*int)和值(nil),整体不为nil
容易踩坑的 nil 比较:接口、切片、map 等
这些类型在 Go 中是“头结构”,哪怕值部分是 nil,只要类型字段非空,整个值就不等于 nil。
-
var s []int和var s2 []int = nil,两者s == s2是true(切片零值就是nil),但var i interface{} = s后,i == nil是false -
var m map[string]int是nil,但var i interface{} = m,再写i == nil→false,必须用i == (map[string]int)(nil)或先类型断言 - 函数类型(
func())、通道(chan int)、接口(io.Reader)同理:不能直接和nil用==比,除非你 100% 确认它没被赋过非nil类型的值
怎么写才不容易出错?
核心原则:避免对非基本指针类型做裸 == nil 判断;优先用显式类型检查或预判上下文。
立即学习“go语言免费学习笔记(深入)”;
- 对接口变量,先做类型断言再判断值是否为
nil:v, ok := x.(fmt.Stringer); if ok && v == nil - 对切片/map/chan,用
len(x) == 0或x == nil都可以(它们的零值定义明确),但别混到接口里去 - 函数类型比较
== nil是合法的,但要注意:两个不同函数字面量即使逻辑相同,也不相等;只有显式赋nil或未初始化的才为真 - 最稳妥的方式:如果不确定类型,就别用
== nil,改用reflect.ValueOf(x).IsNil()(仅限反射场景,性能差,别滥用)
真正麻烦的从来不是两个 *T 比 ==,而是你以为你在比指针,其实你已经在比接口了——类型信息一附着,nil 就不再是那个单纯的 nil 了。










