
在 Go 中,使用 == 即可直接比较两个指针是否指向同一内存地址;但若指针源自方法接收者副本(如值接收者),则其地址必然不同于原始变量,导致指针不等——这是值语义的自然结果,而非比较操作本身的问题。
在 go 中,使用 == 即可直接比较两个指针是否指向同一内存地址;但若指针源自方法接收者副本(如值接收者),则其地址必然不同于原始变量,导致指针不等——这是值语义的自然结果,而非比较操作本身的问题。
Go 语言中,指针相等性判断非常直观:只要两个指针变量存储的内存地址相同,p1 == p2 就返回 true。这正是检查“是否指向同一地址”的标准且唯一正确方式——无需 unsafe、无需反射,更不需要解引用比较内容。
然而,问题代码中 f.Map == &m 返回 false,根本原因不在比较逻辑,而在指针的来源:
func (m1 Map) NewFragment() (f Fragment) {
f.Map = &m1 // ⚠️ &m1 是对形参 m1(m 的副本)取地址!
return
}由于 NewFragment 使用的是值接收者 (m1 Map),调用时 m 会被完整复制一份到栈上,m1 是独立于原始 m 的新变量。因此 &m1 指向的是这个临时副本的地址,而 &m 指向的是原始变量 m 的地址——二者内存位置不同,指针自然不等。
✅ 正确做法:改用指针接收者,确保操作的是原始对象:
func (m1 *Map) NewFragment() Fragment {
return Fragment{Map: m1} // 直接赋值原指针,无需取地址
}
// 调用时需传入指针:
var m Map
f := (&m).NewFragment()
fmt.Println(f.Map == &m) // true ✅⚠️ 注意事项:
- 值接收者方法内对
&receiver取地址,永远无法得到调用方原始变量的地址; - 若必须在值接收者中生成指向“原始语义对象”的指针,请显式传入指针参数(如
func (m1 Map) NewFragment(origin *Map) ...); -
*p == *q比较的是值是否相等,与指针是否同址无关——它可能为true,即使p != q(如两个不同地址存有相同内容的Map{})。
总结:Go 的指针比较 == 完全可靠;所谓“指针不等”,往往暴露的是接收者语义理解偏差。牢记——值接收者 = 复制一份再操作,指针接收者 = 直接操作原对象。

















