为什么从映射中使用指针接收器调用方法时对象状态不会改变?
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
?
时,原始对象以某种方式被复制到地图中
为什么调用带有指针接收器的方法不会改变对象?
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
的年龄无关。
考虑以下代码:
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
?
为什么调用带有指针接收器的方法不会改变对象?
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
的年龄无关。