Go中指针相等仅取决于是否指向同一内存地址或同为nil;==比较不关心值、内容或结构体字段,不同类型指针不可比较,零大小结构体指针可能因地址复用而意外相等。
Go 中两个指针相等,只看它们是否指向**同一块内存地址**,或是否都为 nil;值相同、结构体内容一样、甚至都是 &struct{}{},都不保证指针相等。
Go 允许直接用 == 或 != 比较同类型指针,但结果完全取决于底层地址是否一致:
p1 == p2 为 true 当且仅当 p1 和 p2 存储的是同一个地址(比如都指向变量 a),或两者都是 nil
*p1 == *p2 成立(值相等),p1 == p2 仍可能为 false —— 它们只是“长得像”,不是“同一个人”*int 和 *int64)无法直接比较,编译报错:mismatched types *int and *int64
func main() {
a, b := 42, 42
p1 := &a
p2 := &b
fmt.Println(p1 == p2) // false —— 不同变量,不同地址
fmt.Println(*p1 == *p2) // true —— 值相同,但和指针比较无关
}
对结构体指针使用 ==,比的是指针本身,不是它指向的字段。想比内容,必须解引用:
p1 == p2:只在 p1 和 p2 是同一个结构体实例的地址时才为 true
*p1 == *p2:要求结构体所有字段可比较(不能含 []int、map[string]int 或函数),否则编译失败data *string),*p1 == *p2 仍只比指针地址,不比 *data 的值type User struct {
Name string
Age int
}
u1 := &User{"Alice", 30}
u2 := &User{"Alice", 30}
fmt.Println(u1 == u2) // false
fmt.Println(*u1 == *u2) // true —— 字段都可比较,且值相同
这是最容易踩坑的冷知识:指向 struct{} 这类零大小变量的指针,在接口中比较时可能“意外相等”,哪怕它们来自不同调用:
&struct{}{} 多次调用返回的指针地址相同interface{},one == two 可能返回 true,但你根本没创建同一个对象byte 字段或注释字段即可)type fake struct{ _ [0]byte } // 非零大小,强制分配独立地址
// 而不是 type fake struct{} —— 危险!
函数名本身不可比较:someFunc == someFunc 编译失败,报错 func can only be compared to nil:
f == nil
reflect.ValueOf(f).Pointer()
import "reflect"
func foo() {}
func bar() {}
fmt.Println(reflect.ValueOf(foo).Pointer() == reflect.ValueOf(foo).Pointer()) // true
fmt.Println(refl
ect.ValueOf(foo).Pointer() == reflect.ValueOf(bar).Pointer()) // false
真正难的不是写对 ==,而是意识到你在比什么——地址?值?语义唯一性?一旦把 == 当成“逻辑相等”用,尤其混入接口、零大小类型或函数,就很容易被 Go 的底层行为反向教育。