【发布时间】:2020-10-15 20:57:37
【问题描述】:
好的,对于一些简化的设置,在这个例子中,我们有三个结构 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
}
}
这种方法背后的思想是,通过改变指针指向的位置,我们可以确保agg.vals 中的comp 指针始终指向给定comp 对象的最新迭代。
至于这种方法背后的原因,遍历整个 agg.vals 数组以查找给定 comp 对象的索引将 a) 由于数组的(相当大)大小而计算量很大,并且b) 要求在搜索期间通过内部sync.Mutex 锁定agg,以阻止不同的线程访问该对象,这两者都是不可取的。此外假设不可能将agg.value 制作成地图以方便更新。
由于上面实现的NewComp不起作用,我的问题是上面的函数是否有任何明显的错误,或者我在这里的想法是否犯了一些基本错误?
由于这可能会有所帮助,这里还有一个示例,其中通过指针的指针进行更新按预期工作:
type wrks struct {
id uint64
val1 *comp
val2 *comp
}
func compute() *comp {...}
func updateComp(c **comp) {
*c = compute()
}
func processObj(o *obj) {
updateComp(&o.val1)
updateComp(&o.val2)
}
我看不出两者之间的根本区别,但我可能在这一点上盯着这个看太久了。
【问题讨论】:
标签: dictionary go pointers struct