My solution would be as follows, but is there a race condition in the following code (will it ever panic)?
c := make(chan struct{})
for i := 0; i < 1000000; i++ {
go func() {
select {
case <-c:
default:
close(c)
}
}()
}
I would assume yes, but go test -race doesn't detect it and empirically I couldn't get it to panic.
You launch multiple goroutines without synchronization. So they run concurrently. It may happen 2 of them evaluates <-c
in parallel, seeing it's a blocking operation, so both will choose the default
case. At that point, both of those 2 goroutines will try to close the channel, and only one of them will succeed, the other will panic: you can't close a closed channel.
This is not a race condition because you don't read/modify variables concurrently, but attempting to close a closed channel is a runtime panic (so the race detector will never catch this).
When there are multiple goroutines sending on a channel, wait for all to complete and then close the channel in a single goroutine. Do not attempt to close a channel from multiple goroutines.