How to create an associative map in golang?

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

How to create an associative map in golang?

问题

我正在尝试创建一个"关联"映射。问题在于superMap收集了aMap的所有值。
基本上,即使我只想在每次循环中存储一个aMap的实例,最终我会存储当前实例以及所有先前的循环。supermap[value] = amap[value]。然而,下面的代码片段存储了supermap[value] = amap。原因是我找不到任何修复这个问题的方法。如果我在每次循环后删除aMap的旧值,它们也会从supermap中删除。

package main

import (
	"fmt"
)

func main() {

	aData := map[int]string{
		0: "apple",
		1: "samsung",
		2: "htc",
		3: "sony",
	}

	dir := []string{"user", "doc", "bin", "src"}

	aMap := make(map[int]string)
	superMap := make(map[string]map[int]string)

	for k, v := range dir {
		aMap[k] = aData[k]
		superMap[v] = aMap

	}

	hello(superMap)

}

func hello(superMap map[string]map[int]string) {
	fmt.Printf("superMap of user is %v \n", superMap["user"])

	cnt := len(superMap["user"])
	if cnt > 1 {
		fmt.Printf("expected only one value received %v", cnt)
	}
}

你可以在这里运行这段代码:Play

英文:

I'm trying to create an 'associative' map. The issue is that the superMap collects all the values of aMap.
Basically even if I want to store only one instance of amap on each look I endup storing the current instance plus all the previous loops. supermap[value] = amap[value] . However the snippet below stores supermap[value] = amap. The reason is that I can't find any way to fix this. If I delete the old values of aMap after each loop they are deleted from supermap as well.

  package main
    
    import (
	"fmt"
)

func main() {

	aData := map[int]string{
		0: "apple",
		1: "samsung",
		2: "htc",
		3: "sony",
	}

	dir := []string{"user", "doc", "bin", "src"}

	aMap := make(map[int]string)
	superMap := make(map[string]map[int]string)

	for k, v := range dir {
		aMap[k] = aData[k]
		superMap[v] = aMap

		
	}
	hello(superMap)

}

func hello(superMap map[string]map[int]string) {
	fmt.Printf("superMap of user is %v \n", superMap["user"])
	
	cnt := len(superMap["user"])
	if cnt > 1{
	
	
	fmt.Printf("expected only one value received %v", cnt)
	}
}

Play

答案1

得分: 5

根据Arjan在评论中的说法,你需要将aMap的创建移到for循环中。原因是,在你发布的原始代码中,你正在处理内存中的一个aMap实例。这意味着只创建了一个名为aMap的映射,并且当你将另一个变量赋值为aMap的值时,你正在“分配一个引用”。这意味着,任何保存引用(指向aMap)的变量在状态发生变化时,所有其他变量也会观察到,因为它们都解析为内存中的同一个对象。

aMap移动到for/range循环中时,这意味着将创建4个单独的aMap实例,每个实例都有自己的内存。修改其中一个aMap的状态不会影响其他实例,因为它们是内存中的独立对象。现在,如果你将其中一个对象再次与另一个变量进行引用,那么你将陷入与第一种情况相同的困境。

package main

import (
	"fmt"
)

func main() {

	aData := map[int]string{
		0: "apple",
		1: "samsung",
		2: "htc",
		3: "sony",
	}

	dir := []string{"user", "doc", "bin", "src"}

	superMap := make(map[string]map[int]string)

	for k, v := range dir {
		aMap := make(map[int]string) //在循环中创建多个映射实例
		aMap[k] = aData[k]
		superMap[v] = aMap

	}

	hello(superMap)
}

func hello(superMap map[string]map[int]string) {
	fmt.Printf("user的superMap为%v \n", superMap["user"])
	cnt := len(superMap["user"])

	if cnt > 1 {
		fmt.Printf("预期只接收到一个值,实际接收到%v个", cnt)
	}
}

以上是翻译好的代码部分。

英文:

As Arjan said in the comment, you need to move the creation of aMap into the for loop. The reason is because, in the original code you posted you are dealing with one instance of aMap in memory. That means, only one map called aMap is created and when you assign another variable to the value of aMap you are assigning a reference. This means, any variable that hold a reference (to aMap) where state is mutated, will be observed in all other variables also holding the reference because they all resolve to the same object in memory.

When the aMap is moved into the for/range loop, this means that 4 individual instances of aMap will be created all with their own memory. Mutating the state of one of those aMaps will not affect the others because they are their own objects in memory. Now, if you took one of those objects and made a reference to it again with another variable then you'd end up in the same boat as the first case.

package main

import (
	"fmt"
)

func main() {

	aData := map[int]string{
		0: "apple",
		1: "samsung",
		2: "htc",
		3: "sony",
	}

	dir := []string{"user", "doc", "bin", "src"}

	//aMap := make(map[int]string) //only one map instance is created in memory
	superMap := make(map[string]map[int]string)

	for k, v := range dir {
        //multiple map instances are created in memory
		aMap := make(map[int]string)
		aMap[k] = aData[k]
		superMap[v] = aMap

	}

	hello(superMap)
}

func hello(superMap map[string]map[int]string) {
	fmt.Printf("superMap of user is %v \n", superMap["user"])
	cnt := len(superMap["user"])

	if cnt > 1 {
		fmt.Printf("expected only one value received %v", cnt)
	}
}

huangapple
  • 本文由 发表于 2014年4月15日 00:09:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/23064933.html
匿名

发表评论

匿名网友

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

确定