我想循环遍历结构体切片,并通过将每个结构体传递给函数来填充结构体字段(这是一个映射)。
我有以下结构
type thing struct {
topicThing map[string]int
}
Run Code Online (Sandbox Code Playgroud)
我有以下功能
func main() {
ths := make([]thing, 0)
for i := 0; i < 10; i++ {
var th thing
ths = append(ths, th)
}
for _, th := range ths {
dothing(&th)
}
for _, th := range ths {
fmt.Println(th.topicThing)
}
}
func dothing(th *thing) {
tc := make(map[string]int)
tc["Hello"] = 1
tc["Bye"] = 2
th.topicThing = tc
}
Run Code Online (Sandbox Code Playgroud)
main 函数创建一个事物切片(称为 ths),并通过迭代将每个事物传递给 dothing() 函数。在 dothing() 中,我创建一个新映射,用数据填充它,并将其分配给传入事物的属性。然而,当我们在主函数中迭代 ths 来打印每个事物的 topicThing 时,地图是空的。
由于 make() 在堆中创建对象,我希望即使在函数作用域之外也可以访问它。谁能告诉我为什么会发生这种情况?
PS如果我更改 dothing() 函数,如下所示:
func dothing(th *thing) {
th.topicThing["Hello"] = 1
th.topicThing["Bye"] = 2
}
Run Code Online (Sandbox Code Playgroud)
该代码按预期工作,这意味着在主函数中访问时地图会填充数据。
复制range您的对象。所以当你这样做时,
for _, th := range ths {
dothing(&th)
}
Run Code Online (Sandbox Code Playgroud)
你实际上是dothing在副本上。
例如,这样main:
func main() {
ths := make([]thing, 0)
for i := 0; i < 10; i++ {
var th thing
ths = append(ths, th)
}
for _, th := range ths {
dothing(&th)
fmt.Println(th.topicThing)
}
Run Code Online (Sandbox Code Playgroud)
它会打印正确的内容,因为我们仍在处理副本。
为了不复制,请使用数组索引:
for idx, _ := range ths {
dothing(&ths[idx])
}
Run Code Online (Sandbox Code Playgroud)