2 回答
TA贡献1862条经验 获得超7个赞
方法 1 中的问题是您没有获取字符串的地址,而是获取了它所在变量的地址。在 Go 中,&v返回变量的地址v。当你有这样的循环时:
for k, v := range aMap {
...
}
您在循环开始时声明的变量k和v在整个循环中使用的变量是相同的。它们只是在每次迭代中被分配了不同的值。在该循环中,&v总是计算出相同的值: 的地址v。这就是为什么您的所有地图条目都出现在"foo":"foo"中的最后一个值v,并且它仍然存在。
您可以通过更改字符串值来查看此行为。所有的地图键都会改变:
*bMap["foo"] = "quux"
fmt.Println(*bMap["bar"]) // prints "quux"
方法 2 有效,因为函数的每次调用都有自己的局部变量。Go 保证,如果您从函数返回局部变量的地址,该变量将被分配在堆上,只要需要它就可以使用它。所以你的辅助函数告诉 Go 分配一个新string变量,将传入的字符串复制到它,然后返回它的地址。
这是另一种可行的方法:
dMap := make(map[string]*string)
for k, v := range(aMap){
dMap[k] = new(string)
*dMap[k] = v
}
这会分配一个新的字符串变量,将其地址保存在映射中,然后将 v 复制到其中。如果您要经常这样做,辅助函数可能是最好的。
您尝试的代码如下:
v := "foo"
val := *v
bMap[key] = &val
不起作用,因为您说“v 是一个字符串;现在将字符串指向的值存储在 val 中”,但该字符串不是指针。
TA贡献1854条经验 获得超8个赞
问题中的第一种方法使用v所有键的单个循环变量的地址。您看到的值是最后一个设置为 的值v。
通过为每次迭代声明一个新变量并获取该变量的地址来修复。
bMap := make(map[string]*string)
for k, v := range aMap {
v := v // declare new variable v initialized with value from outer v
bMap[k] = &v
}
问题中的第二种方法还为循环中的每次迭代声明了一个新变量。新变量是函数参数。
这个答案显示了解决这个问题的惯用方法。请参阅Go 常见问题解答:作为 goroutine 运行的闭包会发生什么?在闭包和 goroutine 的上下文中讨论相同的问题。
- 2 回答
- 0 关注
- 186 浏览
添加回答
举报
