Golang updating maps and variables in an object

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

Golang updating maps and variables in an object

问题

我发现了一些行为看起来有点奇怪,如果有人能解释一下为什么会这样工作就好了。

假设我们有一个像这样的结构体/对象:

type Game struct {
    players map[string]Profile
}

type Profile struct {
    name string
    things map[string]string
}

现在假设我们稍后调用一个Game方法,像这样:

func (g *Game) someMethod(playerName string) {
    p, _ := g.players[playerName]
    fmt.Println("P Name: " + p.name)
    fmt.Println("Map contents: " + p.things["something"])

    // 假设这里 p.name 当前等于 "bob",p.things["something"] 当前等于 "this"

    p.name = "fred"
    p.things["something"] = "that"
}

第一次调用someMethod()时,p.name 将等于 "bob",p.things["something"] 将等于 "this"。在更新了这些值之后,如果我们在方法内部立即再次检查它们,p.name 将等于 "fred",p.things 将等于 "that"。

然而,下一次调用这个方法时,p.things 仍然等于 "that",但是 p.name 回到了等于 "bob",而不是更新后的值 "fred"。我唯一找到的解决方法是在更新了 p.name 之后添加以下代码:

g.players[playerName] = p

所以,我的问题是,为什么在 p 对象内部更新 map 可以成功地更新它,使得下一次从 Game 对象中检索 p 时,p 的 map 有新的数据,但是当我们更新 p.name 时,它会恢复到旧的值,除非我们手动将 p 对象添加回 Game 对象的 map 中?

英文:

I've found some behavior that seems a little strange, and it would be nice if someone could explain to me why it works this way.

Let's say we have a struct / object like this:

type Game struct {
    players map[string]Profile
}

type Profile struct {
    name string
    things map[string]string
}

Now let's say later on we call a Game method like this:

func (g *Game) someMethod(playerName string) {
    p, _ := g.players[playerName]
    fmt.Println("P Name:  " + p.name)
    fmt.Println("Map contents:  " + p.things["something"])

    // let's assume here p.name currently equals "bob" and p.things["something"] currently equals "this"

    p.name = "fred"
    p.things["something"] = "that"
}

The very first time we call someMethod(), p.name will equal "bob" and p.things["something"] will equal "this". After updating the values, if we immediately checked them again while still inside the method, p.name would equal "fred" and p.things "that".

However the next time we call this method, p.things will still equal "that" but p.name goes back to equaling "bob" instead of having the updated value of "fred". The only way I've found around this is to add this code after p.name has been updated:

g.players[playerName] = p

So, my question is, why does updating the map within the p object successfully update it so the next time we retrieve p from the Game object, p's map has the new data, but when we update p.name it reverts to the old value unless we manually add the p object back to the Game object's map?

答案1

得分: 2

someMethod中的p是profile结构体的一个副本。如果你想要在map中更新profile,你需要使用一个指针,并且使用类型为map[string]*Profile的map。

至于p.things,虽然p是结构体的一个副本,但是map本身包含对底层数据的引用。换句话说,你不需要一个指向map的指针来操作它的内容,而且很少使用指向map的指针。

英文:

p within someMethod is a copy of the profile struct. If you want to update the profile within the map, you will need to use a pointer, and a map of type map[string]*Profile

As for p.things, even though p is a copy of the struct, the map itself contains a reference to the underlying date. In other words, you don't need a pointer to a map to manipulate it's contents, and you rarely use a pointer to a map.

huangapple
  • 本文由 发表于 2014年7月29日 09:34:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/25006961.html
匿名

发表评论

匿名网友

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

确定