Reputation: 63
I don't seem to totally understand maps in Go.
I have this code:
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)
}
Now wherever the threadfunc function uses the fetchlocal variable Go (go -race) says warning: data race. I also got a few panics already. But why? The fetchlocal variable isn't used by any other goroutine.
Can someone enlighten me, please?
Upvotes: 6
Views: 2362
Reputation: 6826
I'm assuming your fetch := map[string]int{some data}
was actually supposed to be: fetch := map[string][]int{..some data..}
.
For this to be a race threadfunc
must be changing a value within fetchlocal
or something else must be changing the value within fetch
.
This is to say a slice is a actually:
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
When you are copying the elements from one map to another you are not doing a deep copy of the slices (you are just creating a new struct with the same Data,Len,Cap), that is so say fetch["foo"].Data == fetchlocal["foo"].Data
.
Therefore you can say fetch[someExistingKey] = someNewValue
and this will not race with threadfunc
, but if you say fetch[someExistingKey][x] == foobar
or fetchlocal[someExistingKey][x] == foobar
the race will be on.
If fetchlocal
needs to mutated by threadfunc
you could change your inner loop to look like:
for key, value := range fetch {
if condition {
newVal := make([]int, len(value))
copy(newVal, val)
fetchlocal[key] = newVal
}
}
Or alternatively, do the copy inside threadfunc
as needed before mutating.
P.S. If you shared your actual threadfunc
or code that is modifying fetch
while these two loops are running, we will be able to help more.
Upvotes: 3