我是golang的新手,所以我试图从其他语言(例如Java/JavaScript)中调整我的思维,并将其应用于golang。在大多数情况下,这是很直接的。然而,当涉及到跨图迭代和修改值时,我就有点束手无策了。
考虑一下下面的示例程序。
package main
import "fmt"
type data struct {
ID string
Value string
}
func main() {
myData := make(map[string]data)
foo := data{ID: "one", Value: "oneval"}
myData["one"] = foo
foo = data{ID: "two", Value: "twoval"}
myData["two"] = foo
for _, v := range myData {
fmt.Println(v.Value)
v.Value = "kenny"
}
for _, v := range myData {
fmt.Println(v.Value)
}
}
在大多数语言中,我希望输出结果是。
oneval
twoval
kenny
kenny
当然,这不是。它是
oneval
twoval
oneval
twoval
感谢这个SO答案(How to update map values in Go),解决方案是将元素 "重新分配 "到地图中。哎哟,不过还好。
另一个选择是创建一个指向该结构的指针映射,但这最终导致了相关的悖论。考虑一下这个更新的程序。
package main
import "fmt"
type data struct {
ID string
Value string
}
func main() {
// Now it's a map of struct pointers...
myData := make(map[string]*data)
foo := data{ID: "one", Value: "oneval"}
myData["one"] = &foo
foo = data{ID: "two", Value: "twoval"}
myData["two"] = &foo
for _, v := range myData {
fmt.Println(v.Value)
v.Value = "kenny"
}
for _, v := range myData {
fmt.Println(v.Value)
}
}
我本来以为输出结果会是。
oneval
twoval
kenny
kenny
其实是这样的。
twoval
kenny
kenny
kenny
foo
因此,要想让它如愿以偿地工作,唯一的办法就是这样做。
package main
import "fmt"
type data struct {
ID string
Value string
}
func main() {
// Now it's a map of struct pointers...
myData := make(map[string]*data)
{
foo := data{ID: "one", Value: "oneval"}
myData["one"] = &foo
}
// Really, anything to make 'foo' go out of scope
foo := data{ID: "two", Value: "twoval"}
myData["two"] = &foo
for _, v := range myData {
fmt.Println(v.Value)
v.Value = "kenny"
}
for _, v := range myData {
fmt.Println(v.Value)
}
}
很明显,一定有更好的方法。所以我问你们--StackOverflow社区的智者们--到底发生了什么?