如何解决通过指针的指针更新结构不起作用
好吧,对于某些简化的设置,在此示例中,我们具有三个结构comp
,agg
和cache
,看起来像这样:
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()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。