gpt4 book ai didi

go - 取消引用指针的类型断言是内存写入吗?

转载 作者:IT王子 更新时间:2023-10-29 01:36:29 28 4
gpt4 key购买 nike

go race detector 以一种对我来说毫无意义的方式提示我的代码,但我想 race detector 的作者比我更了解这一点。

我有这个闭包:

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
}

这是另一个 goroutine 的相关部分:

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 是一个接口(interface),*datastore.T 实现了该接口(interface)。

竞争检测器提示闭包和另一个 goroutine 存在数据竞争。另一个 goroutine 写入,闭包读取。考虑到 sync.RWMutex 就位,我看不出这会如何冲突。

最佳答案

取消引用指针的类型断言不会写入 Go 中的变量。

这段代码

for read := range [chan of datastore.F] {
s.lock.Lock()
s.fs[read.Fi()] = &read
s.lock.Unlock()
}

将映射值设置为局部变量read 的地址。变量 read 的范围在 for 循环 block 之外,并且在循环的每次迭代中都会被修改。所有映射值都包含相同的指针,这可能不是您想要的。

闭包通过取消引用映射中的指针来读取变量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 中很少使用指向接口(interface)的指针。解决此问题的首选方法是将类型 *datastore.F 的所有使用更改为 datastore.F。此更改消除了跨 goroutine 边界对变量 read 的引用,并消除了不必要的间接级别。

关于go - 取消引用指针的类型断言是内存写入吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31395316/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com