Golang:在声明的函数之外访问地图对象

sk3*_*311 -1 go

我想循环遍历结构体切片,并通过将每个结构体传递给函数来填充结构体字段(这是一个映射)。

我有以下结构

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)

该代码按预期工作,这意味着在主函数中访问时地图会填充数据。

Bes*_*lma 5

复制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)