Go中调用map存储的指针接收者方法为何未修改原对象状态
问题根本原因
你猜测的方向是对的,核心问题出在方法值绑定的接收者是创建时的实例指针,而你返回值类型时发生了实例拷贝:
- 在
New函数内部,你创建的是局部值类型实例p,执行p.M["1"] = p.Add时,因为Add是指针接收者方法,Go会自动对当前可寻址的局部p取指针作为该方法值的接收者,也就是这个Add方法已经绑定了New函数内局部p的内存地址。 - 你的
New函数返回的是Person值类型,执行return p时会对局部p做值拷贝,返回给main函数的是一个全新的实例,和New内部的局部p是两个完全独立的内存对象。只有map作为引用类型被拷贝了指针,所以两个实例共享同一个Mmap。 - 后续main里调用
Run方法时,接收者是main里新实例的指针,修改的是新实例的Age;而调用M里存的Add方法时,用的还是当初绑定的New内部旧实例的指针,修改的是旧实例的Age,自然不会同步到main里的新实例上。
修复方案
只需要把New函数的返回值改为指针类型即可,避免实例拷贝,让方法值绑定的接收者和main里使用的实例是同一个:
// 修改New函数返回值为*Person func New() *Person { p := &Person{1, make(map[string]func())} p.M["1"] = p.Add return p }
修改后运行结果就会符合预期:
age before 1 Age before mutating in Run 1 Age before mutating in Add 2 Age after mutating in Add 3 Age after mutating in Run 3 age after 3
内容的提问来源于stack exchange,提问作者abhijat
相关产品推荐
相关产品推荐

