跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

Go 中指针比较:理解 == 是比较地址还是值

Go 中指针支持直接比较(p == q),结果为 true 当且仅当二者指向同一变量或均为 nil;但若使用 *p == *q,实际比较的是所指向的值而非地址,这常导致误解。 go 中指针支持直接比较(`p == q`),结果为 true 当且仅当二者指向同一变量或均为 nil;但若使用 `*p == *q`,实际比较的是所指向的值而非地址,这常导致误解。 在 Go 中,指针是可比较的类型,其相等性语义非常明确: 两个指针变量 p 和 q 满足 p == q,当且仅当它们存储的内存地址相同,或二者同时为 nil 。这是底层地址层面的严格比较,与所指向的数据内容无关。 而问题中的代码:
fmt.Println(*p == *q) // 输出 true
看似在“比较指针”,实则完全不是——*p 和 *q 是 解引用操作 ,返回的是各自指向变量的值(即 int 类型的 1)。因此 *p == *q 等价于 1 == 1,自然为 true。这与指针本身是否相同毫无关系。 要真正验证指针是否相等,必须省略解引用符号,直接比较指针变量:
fmt.Println(p == q) // false —— 因为 f() 和 f2() 分别在独立栈帧中创建了不同变量 v 和 w,地址必然不同 fmt.Printf("p = %p\n", p) // 如 0xc0000140a0 fmt.Printf("q = %p\n", q) // 如 0xc0000140b0(地址不同)
⚠️ 注意事项: 每次调用 f() 或 f2() 都会在函数栈上新建局部变量(v 和 w),即使值相同,它们的地址也互不重叠; Go 编译器 不会 因值相同而复用地址或进行“指针折叠”; 若需判断两个指针是否逻辑上“指向等价数据”,应显式比较解引用后的值(如 *p == *q),但这属于业务逻辑,而非指针相等性; 对 nil 指针解引用会 panic,比较前建议先判空:if p != nil && q != nil && *p == *q { ... }。 总结:p == q 判断「是否同一地址」,*p == *q 判断「值是否相等」——二者语义截然不同,混淆将引发隐蔽逻辑错误。正确使用指针比较,是写出健壮、可维护 Go 代码的基础。

相关文章