I’m trying to update a map from multiple goroutines, but the results seem inconsistent. Sometimes keys are missing or values are wrong.
Here’s my code: package main
import (
"fmt"
"sync"
)
func main() {
counter := make(map[string]int)
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
key := fmt.Sprintf("key%d", id)
counter[key] = id * 10
}(i)
}
wg.Wait()
fmt.Println(counter)
}
Sometimes the output is missing some keys or has incorrect values.
I tried adding time.Sleep() inside the goroutine, but that doesn’t fix it reliably.
fmt.Printlnis guaranteed to be called after all the goroutines finish) but it is not because the goroutines spawned in the loop are executed concurrently with each other, and they all mutate the map. So should you run your example after building it withgo build -race, you would see the Go runtime crash your program almost immediately, reporting a data race. Go has no concurrency-safe builtin types, and most 3rd-party types are not concurrency-safe either, unless documented.