为什么从映射中使用指针接收器调用方法时对象状态不会改变?

Why does object state not change when calling methods with a pointer receiver from within a map?

考虑以下代码:

package main

import (
    "fmt"
)

type Person struct {
    Age int
    M   map[string]func()
}

func New() Person {
    p := Person{1, make(map[string]func())}
    p.M["1"] = p.Add
    return p
}

func (p *Person) Add() {
    fmt.Println("Age before mutating in Add", p.Age)
    p.Age += 1 // here age should become 3
    fmt.Println("Age after mutating in Add", p.Age)
}

func (p *Person) Run() {
    fmt.Println("Age before mutating in Run", p.Age)
    p.Age += 1 // here age should be 2
    p.M["1"]()
    fmt.Println("Age after mutating in Run", p.Age)
}

func main() {
    p := New()
    fmt.Println("age before", p.Age)
    p.Run()
    fmt.Println("age after", p.Age)
}

这会产生输出

age before 1
Age before mutating in Run 1
Age before mutating in Add 1
Age after mutating in Add 2
Age after mutating in Run 2
age after 2

这里M是一个结构体的映射成员,它存储了同一个结构体对字符串的方法。

在 main 中,我们实例化了一个非指针结构值。

然后我们在定义为具有指针接收器的结构上调用方法 Run应该与方法共享一个指向结构的指针,这应该允许方法改变原始结构。

Run 中,我们通过地图调用存储在地图中的函数 Add。但这并没有改变结构,事实上它似乎在新创建时对对象的状态进行操作。

Add 内的任何更改都将在 Run 结束时丢失,尽管 Add 也使用指针接收器声明。

我怀疑这是因为在调用 p.M["1"] = p.Add?

时,原始对象以某种方式被复制到地图中

为什么调用带有指针接收器的方法不会改变对象?

游乐场linkhttps://play.golang.org/p/CRer_rT8_sj

New returns 是 Person 而不是 *Person.

写的时候

p := New()

它从 New 构造一个 Person pnew 并将其 Add 方法添加到 pnew.M 开始。然后它 returns pnew.

然后这个pnew被分配给p,这是一个不同的变量。所以 p.M 现在包含 pnew 的 Add 方法。当您在 运行 中执行 p.M["1"]() 时,pnew 的年龄会增加(这与 p 的年龄无关。