接收channel如何优雅的退出
// 1. 场景:只有一个接收通道。使用for range,如果channel关闭则会自动退出循环
go func(in <-chan int) {
// Using for-range to exit goroutine
// range has the ability to detect the close/end of a channel
for x := range in {
fmt.Printf("Process %d\n", x)
}
}(inCh)
// 2. 场景:接收多通道,但是只要有一个通道关闭就结束。使用select ok,如果channel关闭,则ok为false
go func() {
for { // in for-select using ok to exit goroutine
select {
case x, ok := <-in:
if !ok {
return
}
fmt.Printf("Process %d\n", x)
processedCnt++
case <-t.C:
fmt.Printf("Working, processedCnt = %d\n", processedCnt)
}
}
}()
// 3. 场景:接收多个通道,只有所有通道都关闭才退出。使用select ok,并把关闭的channel置为nil(这样不会被select到)
go func() {
for { // in for-select using ok to exit goroutine
select {
case x, ok := <-in1:
if !ok {
in1 = nil
}
// Process
case y, ok := <-in2:
if !ok {
in2 = nil
}
// Process
case <-t.C:
fmt.Printf("Working, processedCnt = %d\n", processedCnt)
}
// If both in channel are closed, goroutine exit
if in1 == nil && in2 == nil {
return
}
}
}()
// 4. 场景:有独立的退出通知通道,可以主动退出
func worker(stopCh <-chan struct{}) {
go func() {
defer fmt.Println("worker exit")
// Using stop channel explicit exit
for {
select {
case <-stopCh:
fmt.Println("Recv stop signal")
return
case <-t.C:
fmt.Println("Working .")
}
}
}()
return
}