【问题标题】:Golang updating maps and variables in an objectGolang 更新对象中的地图和变量
【发布时间】:2014-07-29 01:34:37
【问题描述】:

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

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

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"])

    // let's assume here p.name currently equals "bob" and p.things["something"] currently equals "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 对象中的地图会成功更新它,所以下次我们从 Game 对象中检索 p 时,p 的地图有新数据,但是当我们更新 p.name 时,它​​会恢复为除非我们手动将 p 对象添加回 Game 对象的地图,否则旧值?

【问题讨论】:

    标签: go maps


    【解决方案1】:

    someMethod 中的p 是配置文件结构的副本。如果要在地图中更新配置文件,则需要使用指针和map[string]*Profile 类型的地图

    对于p.things,尽管p 是结构的副本,但映射本身包含对基础日期的引用。换句话说,您不需要指向地图的指针来操作其内容,而且您很少使用指向地图的指针。

    【讨论】:

    • 您不必更改地图本身。你可以设置p := &g.players[playername],然后设置p->name = fred
    • @AustinMullins:这是不正确的。地图内容不可寻址,因此&g.players[playerName] 将无法编译。
    • You are correct。我对这个事实感到惊讶。
    • @AustinMullins:这是因为地图的内容可能会被其他插入或删除操作移动(故意未定义地图实现)。
    • @SwordofGF: 基本上是的,虽然thing := SomeObject{}thing := &SomeObject{} 更容易看到(如果你感到困惑,请忘记new,它不需要任何东西)。
    猜你喜欢
    • 2017-08-16
    • 1970-01-01
    • 1970-01-01
    • 2020-10-09
    • 2021-12-12
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 2018-06-07
    相关资源
    最近更新 更多