微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

通过指针的指针更新结构不起作用

如何解决通过指针的指针更新结构不起作用

好吧,对于某些简化的设置,在此示例中,我们具有三个结构compaggcache,看起来像这样:

type comp struct {
    id  uint64
    val float64
}

type agg struct {
    id   uint64
    vals []*comp
}

type cache struct {
    compMtx sync.RWMutex
    comps map[uint64]*comp
    aggMtx sync.RWMutex
    aggs  map[uint64]*agg
}

cache具有以下功能添加新的comp值,而在更新的情况下似乎不起作用:

func (c *cache) NewComp(cpNew *comp) {
    compMtx.Lock()
    defer compMtx.Unlock()
    cpOld,ok := c.comps[cpNew.id]
    if ok { // update
        addr := &cpOld // this is of type **comp
        *addr = cpNew
    } else { // new value
        c.comps[cpNew.id] = cpNew
    }
}

方法背后的思想是,通过更改指针的指针指向的位置,我们可以确保comp中的agg.vals指针始终指向给定{{1 }}对象。

由于这种方法背后的原因,迭代整个comp数组以找到给定agg.vals对象的索引将a)由于(相当大)的大小而在计算上是昂贵的b)要求comp搜索期间通过内部agg锁定,以阻止不同的线程访问该对象,这都是不希望的。此外,假设不可能将sync.Mutex放入地图中以便于轻松更新。

由于上述实现的agg.value不起作用,我的问题是上面的函数中是否有任何明显的错误,还是我在这里的思考中犯了一些根本性的错误


这可能会有所帮助,这也是一个示例,其中通过指针的指针进行更新的工作符合预期:

NewComp

我看不到两者之间的根本区别,但是在这一点上,我可能盯着这个看了太长时间。

解决方法

您将指针存储在地图中,因此当从中获取指针时,只需修改指针值,然后将其分配给指针值即可:

cpOld,ok := c.comps[cpNew.id]
if ok { // update
    *cpOld = *cpNew
} else { // new value
    c.comps[cpNew.id] = cpNew
}

请参见Go Playground上的简化示例,以显示其工作原理。

您的原始代码无效,因为cpOld是一个指针,但是它是存储在地图中的指针的副本。如果您修改此cpOld变量的值,则对映射中存储的值没有影响。您无法更改地图中的值,只能在其中重新分配/存储新值。

您应该记住的一件事:更新后,传递给cpNew的{​​{1}}指针将不会“有用”,因为我们没有使用该指针,我们只是使用了指向的值更新地图已经指向的值(存储在地图中的值)。如果您希望指针保持指向相同的值,则别无选择,只能将该指针存储在地图中,就像它是新的一样:

NewComp()

查看相关问题:How to update map values in Go

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。