这其实是个老生常谈的问题了,在例会上被第二次提到,原文见此

本人简单概括一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
type Group struct {
Name string
Persons []Person
}

type Person struct {
Name string //标准名
Alias []string //别名,可以是邮箱、QQ号等
Submit bool // 是否已提交
}

func (p Group) ChangeSomeThingV1() {
for _, person := range p.Persons {
person.Submit = true
}
}

func (p *Group) ChangeSomeThingV2() {
for _, person := range p.Persons {
person.Submit = true
}
}

这两个 ChangeSomeThing() 方法的区别是什么?哪个能够起作用?

答案是:两个都没用

这是一个新手经常会犯的错误,要知道,和 Python 中一样,range 枚举出来的都是副本,修改副本是没有用的

可以这样解决

1
2
3
4
for i := range p.Persons {
p.Persons[i].Submit = true
//person.Submit = true
}

当然,更好的一种方法是改为指针类型,这样可以通过 range 出来的指针修改对象

另一个坑是关于指针接收者的,也就是上面两个方法的区别

不管实体还是指针都可以成功调用两种方法,Golang 会帮你自动转换的(除了直接用 {} 临时创建的对象)

但是,只有接收者为指针的方法能修改对象,这一点要牢记