Goroutines选择带范围循环

时间:2018-12-12 00:42:47

标签: go concurrency channel goroutine

我想产生一个goroutine来监听chan intchan os.Signal类型的两个通道。我希望具体行为取决于在任何一个渠道收到的内容。意味着有些os.Signal可能会导致os.exit(),有些可能不会,通过int接收到的某些chan int可能会打印一条语句,而某些可能会调用一个函数,因此我需要将此gorountine作为始终运行,因为行为不同。我希望这一切都由一个功能完成。

我很难弄清楚如何从语法上实现这一目标。似乎我不能在range块内有select循环,也似乎不能在select循环内有range块。我在网上找不到任何资源。有人可以给我一个例子吗?

1 个答案:

答案 0 :(得分:1)

您可以将select statement放入for循环中(这是语言规范中的示例之一)。与for...range循环不同,这可以让您从两个通道中读取。如果其中一个频道关闭,它也不会自动终止。 receive from a closed channel时,关闭的通道始终准备好接收并始终产生零值,并且它有两种值的形式来告诉您通道是否打开。

您的函数可能看起来很松散

func HandleStuff(numbers <-chan int, signals <-chan os.Signal) {
    var goingToExit bool
    for {
        select {
        case n := <-numbers:
            if n == 0 {
                fmt.Printf("zero\n")
            } else if n == 1 {
                goingToExit = true
            }
        case sig, ok := <-signals:
            if !ok { // the channel is closed
                return
            } else if goingToExit {
                os.Exit(0)
            }
        }
    }
}