目标
我们有goroutine A,B,C以及主进程M
A,B,C和M通过errorch
,finishCh
和singalCh
来互动, 从而实现M捕捉A,B,C中的异常,接受A,B,C全部完成的信号,或者是用户命令行的ctrl+C
M需要等待A,B,C的结果并且M需要自旋等待,
for {
select {
case err = <- ErrorCh:
fmt.Println("Error msg")
return err
case <- FinishCh:
fmt.Println("Completed in success")
return nil
case s := <-c:
fmt.Println("Stopped by signal received" + s.String())
fmt.Println("Completed processing transactions")
return nil
}
}
做法
之前的做法是在A,B,C中分别实现, 这样当A结束任务后,通知M结束进程。
func xxx(){
if condition
close FinishCh
}
问题
会出现A, B, M, C
这样的顺序,此时,在M主进程退出前,B会报出错误,panic: close of closed channel
改进
通过引入A,B,C共享的一个once函数来实现close chan的操作只执行一次
func xxx(){
if condition
once.Do(func() {
close(finishCh)
})
}