This code runs concurrently in many goroutines,the following code is a key and relevant part extracted from the production environment code.:
func check() {
.......check condition......
//skipEnsure and skipNative will not both false here
var wg sync.WaitGroup
if !skipEnsure {
wg.Add(1)
go func(wg *sync.WaitGroup) {
defer wg.Done()
dosomething1()
}(&wg)
}
if !skipNative {
wg.Add(1)
go func(wg *sync.WaitGroup) {
defer wg.Done()
dosomething2()
}(&wg)
}
wg.Wait() //panic here
}
func worker() {
......
go check()
}
func main() {
for i:=0;i<32;i++ {
go worker()
}
ch := make(chan any, 0)
<-ch
}
I can reproduce the issue when WaitGroup is a global variable, but not in the code provided. It can cause panic after running for a while in the production environment.
If I understood you correctly the code looks like this one:
sync.WaitGroup is not designed for such usage. It is not obvious when wg.Add and wg.Wait will be called. If you try to run it with data race detector you can see something like this:
You can use own WaitGroup for each goroutine (as in your example). I cannot imagine any reason against it. For example, this code will work fine, without any data race: