Golang: accessing map object outside the function it was declared in

huangapple go评论83阅读模式
英文:

Golang: accessing map object outside the function it was declared in

问题

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

我有以下结构体:

type thing struct {
    topicThing map[string]int
}

我有以下函数:

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
}

主函数创建了一个thing的切片(称为ths),并通过迭代它们将每个thing传递给dothing()函数。
在dothing()函数内部,我创建了一个新的映射,填充了数据,并将其赋值给传入的thing的属性。然而,当我们在主函数中迭代ths以打印每个thing的topicThing时,映射为空。

由于make()在堆中创建对象,我希望它在函数作用域之外也可以访问。有人可以告诉我为什么会发生这种情况吗?

附注:
如果我将dothing()函数更改如下:

func dothing(th *thing) {
    th.topicThing["Hello"] = 1
    th.topicThing["Bye"] = 2
}

代码将按预期工作,也就是说,当在主函数中访问时,映射中填充了数据。

英文:

I would like to loop through a slice of structs, and populate a struct field (which is a map) by passing in each struct to a function.

I have the below struct

type thing struct {
    topicThing map[string]int
}

and I have the below functions

func main() {
    ths := make([]thing, 0)
    for i := 0; i &lt; 10; i++ {
        var th thing
        ths = append(ths, th)
    }

    for _, th := range ths {
        dothing(&amp;th)
    }

    for _, th := range ths {
        fmt.Println(th.topicThing)
    }
}

func dothing(th *thing) {
    tc := make(map[string]int)
    tc[&quot;Hello&quot;] = 1
    tc[&quot;Bye&quot;] = 2
    th.topicThing = tc
}

The main function creates a slice of things (refered as ths), and passes each thing to the dothing() function by iterating over them.
Within dothing(), I create a new map, populate it with data, and assigns it to the passed in thing's attribute. However, by the time we iterate over ths in the main function to print topicThing of each thing, the map is empty.

Since make() creates objects within the heap, I was hoping it would be accessible even outside of the function scope. Can anyone tell me why this is happening?

P.S.
if I change the dothing() function like below:

func dothing(th *thing) {
    th.topicThing[&quot;Hello&quot;] = 1
    th.topicThing[&quot;Bye&quot;] = 2
}

The code works as expected, meaning the map is populated with data when accessed in the main function.

答案1

得分: 5

range会复制你的对象。所以当你这样做时,

    for _, th := range ths {
        dothing(&amp;th)
    }

实际上是在对副本进行dothing操作。

例如,使用以下main函数:

func main() {
	ths := make([]thing, 0)
	for i := 0; i &lt; 10; i++ {
		var th thing
		ths = append(ths, th)
	}

	for _, th := range ths {
		dothing(&amp;th)
		fmt.Println(th.topicThing)
	}
}

它会打印正确的结果,因为我们仍然在处理副本。

为了避免复制,可以使用数组索引:

    for idx, _ := range ths {
        dothing(&amp;ths[idx])
    }
英文:

The range copies your object.
So when you do this,

    for _, th := range ths {
        dothing(&amp;th)
    }

you are actually dothing on a copy.

For example, with this main:

func main() {
	ths := make([]thing, 0)
	for i := 0; i &lt; 10; i++ {
		var th thing
		ths = append(ths, th)
	}

	for _, th := range ths {
		dothing(&amp;th)
		fmt.Println(th.topicThing)
	}

it will print the right thing, since we are still working on the copy.

In order to not copy, use the array index:

    for idx, _ := range ths {
        dothing(&amp;ths[idx])
    }

huangapple
  • 本文由 发表于 2022年1月22日 23:54:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/70814532.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定