go种族检测器以一种对我来说毫无意义的方式抱怨我的代码,但我想,种族检测器的作者比我更了解这一点。
我有个结论:
func(f *datastore.F) bool {
a, ok := (*f).(*datastore.T)
...
}作为参数传递给这个函数:
func GetFunc(f func(fid *datastore.F) bool) (*datastore.F, bool) {
kvs.lock.RLock()
defer kvs.lock.RUnlock()
for _, v := range kvs.fs {
if f(v) {
return v, true
}
}
return nil, false
}这是另一个峡谷的相关部分:
for read := range [chan of datastore.F] {
s.lock.Lock()
s.fs[read.Fi()] = &read
s.lock.Unlock()
}kvs是这种类型的实例:
type kvstore struct {
lock sync.RWMutex
fs map[datastore.Fi]*datastore.F
}datastore.F是一个接口,*datastore.T实现了这个接口。
竞赛检测器抱怨关闭和另一个goroutine有一个数据竞争。另一个哥鲁丁写着,闭幕式写着。考虑到sync.RWMutex已经到位,我不知道这是如何发生冲突的。
发布于 2015-07-14 00:00:07
取消引用指针的类型断言不会写入Go中的变量。
这段代码
for read := range [chan of datastore.F] {
s.lock.Lock()
s.fs[read.Fi()] = &read
s.lock.Unlock()
}将映射值设置为局部变量read的地址。变量read在for循环块之外有一个作用域,并且在循环中的每一次迭代中都进行修改。所有映射值都包含相同的指针,这可能不是您想要的。
闭包通过取消引用映射中的指针来读取变量read。竞争检测器抱怨是因为读取器(闭包)和写入器( for循环)之间没有同步。
要解决这个问题,在循环中声明一个新变量:
for read := range [chan of datastore.F] {
read := read // <-- Add this line
s.lock.Lock()
s.fs[read.Fi()] = &read
s.lock.Unlock()
}通过此更改,每个映射值指向一个唯一的变量,该变量只设置一次。
在Go中很少使用指向接口的指针。此问题的首选修复方法是将*datastore.F类型的所有用法更改为datastore.F。此更改消除了对变量read的跨goroutine边界的引用,并消除了不必要的间接级别。
https://stackoverflow.com/questions/31395316
复制相似问题