我似乎并不完全了解Go中的 map 。
我有以下代码:
fetch := map[string]int{some data}
for condition {
fetchlocal := map[string]int{}
for key, value := range fetch {
if condition {
fetchlocal[key] = value
}
}
go threadfunc (fetchlocal)
}
现在,无论threadfunc函数在何处使用fetchlocal变量,Go(go -race)都警告:数据争用。我也已经有些 panic 了。但为什么?其他任何goroutine都不使用fetchlocal变量。
有人可以启发我吗?
最佳答案
我假设您的fetch := map[string]int{some data}
实际上应该是:fetch := map[string][]int{..some data..}
。
要使其成为种族,threadfunc
必须更改fetchlocal
中的值,或者其他必须更改fetch
中的值。
也就是说, slice 实际上是:
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
当您将元素从一个映射复制到另一个映射时,不是对 slice 进行深度复制(您只是使用相同的Data,Len,Cap创建一个新结构),即
fetch["foo"].Data == fetchlocal["foo"].Data
。因此,您可以说
fetch[someExistingKey] = someNewValue
,这将不会与threadfunc
竞争,但是如果您说fetch[someExistingKey][x] == foobar
或fetchlocal[someExistingKey][x] == foobar
,竞争将继续进行。如果
fetchlocal
需要被threadfunc
突变,则可以将内部循环更改为:for key, value := range fetch {
if condition {
newVal := make([]int, len(value))
copy(newVal, val)
fetchlocal[key] = newVal
}
}
或者,在进行变异之前,根据需要在
threadfunc
中进行复制。附言如果您在这两个循环运行时共享了实际的
threadfunc
或正在修改fetch
的代码,我们将为您提供更多帮助。关于go - golang ,比赛状况与本地 map ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22987426/