代码很接近,但当发送多个错误时会泄漏goroutines。第一个发送的工人
errChan
退出,因为主goroutine接收到该值。发送到的所有其他工作人员
errChan
永远阻止,因为没有goroutine来接收值。这个
wg.Wait(); close(errChan)
goroutine也永远阻止等待工人完成。
修复有两个方面:使用非阻塞发送到通道并确保
errChan
可以接收至少一个值。
有关更多详细信息,请参阅下面的评论:
func run() error {
var wg sync.WaitGroup
// Create channel with capacity one to ensure that
// a goroutine can send to the channel before this
// goroutine is ready to receive.
errChan := make(chan error, 1) // <-- note 1 here
for i := 0; i < numWorkers; i++ {
wg.Add(1)
go func(num int) {
defer wg.Done()
doSomeWork(num, errChan)
}(i)
}
go func() {
wg.Wait()
// All goroutines are done, but the main goroutine
// will be waiting if there were no errors. Close
// the channel so that the main goroutine receives
// a zero error value.
close(errChan)
}()
// The if statement in the original is not needed because
// the zero value of the error interface is nil.
return <-errChan
}
func doSomeWork(num int, errChan chan<- error) {
if num >= 10 {
select {
case errChan <- errors.New("Greater than 10"):
// Successful send on channel
default:
// Channel is not ready. This implies that
// at least one other goroutine sent an error
// to the channel. There's nothing for us to
// do here. error.
}
}
}
Run the program on the Playground
!