指针比较只看地址不看值,== 判断是否指向同一内存地址;不同类型指针不可直接比较;nil 必须显式判断;零大小结构体指针比较结果不确定。
在 Go 中,== 比较两个指针,判断的是它们是否指向**同一块内存地址**,而不是所指向的值是否相等。这是最常被误解的一点。
p1 和 p2 都指向值为 42 的变量,只要地址不同,p1 == p2 就是 false
p1 == p2 为 true 仅当它们是同一个变量的地址(比如 p2 = p1)*p1 == *p2 —— 但前提是结构体字段都可比较(不能含 slice、map 或函数)Go 是强类型语言,*int 和 *int64 即使底层都是 8 字节,也不能用 == 直接比较,编译器会报错:mismatched types *int and *int64。
var x int = 10 var y int64 = 10 px := &x py := &y // fmt.Println(px == py) // 编译失败
unsafe.Pointer:unsafe.Pointer(px) == unsafe.Pointer(py)
== nil
未初始化的指针默认值是 nil,但 Go 不允许隐式布尔转换,也不能用 if p 这类写法。
var p *int
if p == nil {
fmt.Println("指针为空")
}if p != nil { fmt.Println(*p) },否则运行时 panicnil 调用会 panic(除非方法内主动判空),建议在入口加 if p == nil { return }
对于空结构体 struct{} 或只含零大小字段的类型,多个不同变量的指针在比较时可能意外相等 —— 这是 Go 规范允许的实现细节,不是 bug。
var a, b struct{}
pa, pb := &a, &b
fmt.Println(pa == pb) // 可能 true,也可能 false,不可依赖== 判断两个零大小变量是否“不同”,也不能用它做唯一性标识reflect.ValueOf(p).Pointer() 获取绝对地址,或改用带字段的结构体nil 处理和零大小类型这三处最容易漏掉细节。尤其在写通用工具或封装接口时,别假设指针相等意味着值相等,也别