我有两个独立产生数据的goroutine,每个goroutine将它们发送到一个通道。在我的主要例程中,我希望在输入时使用这些输出中的每一个,但不关心它们的输入顺序。每个通道在耗尽输出时都会关闭。尽管select语句是像这样独立消费输入的最好语法,但我还没有看到一个简洁的方式来循环每个通道,直到两个通道都关闭。当所有通道关闭时突然出现select语句
for {
select {
case p, ok := <-mins:
if ok {
fmt.Println("Min:", p) //consume output
}
case p, ok := <-maxs:
if ok {
fmt.Println("Max:", p) //consume output
}
//default: //can't guarantee this won't happen while channels are open
// break //ideally I would leave the infinite loop
//only when both channels are done
}
}
我能想到做到最好如下(只是勾勒,可能有编译错误):
for {
minDone, maxDone := false, false
select {
case p, ok := <-mins:
if ok {
fmt.Println("Min:", p) //consume output
} else {
minDone = true
}
case p, ok := <-maxs:
if ok {
fmt.Println("Max:", p) //consume output
} else {
maxDone = true
}
}
if (minDone && maxDone) {break}
}
但这样子,如果你有超过它的工作会得到站不住脚两个或三个频道。我唯一知道的另一种方法是在switch语句中使用一个timout案例,该案例要么足够小,以避免提前退出,要么将太多停机时间注入最终的循环中。有没有更好的方法来测试select语句中的通道?
我可能会将'if'语句包装到本地函数中。它不那么混乱,功能名称会帮助更明显地发生什么(沿着这些方向:http://play.golang.org/p/347KZdI_Gs)。 – Chris
+1为非聪明的解决方案。将这些通道设置为零是很重要的,这样select就不会浪费时间,但我可能会使用一个单独的变量来计算打开通道的数量。对于n = 2; N> 0; {然后每次你设置一个频道到零,n--。 – Sonia
来自语言规范:“由于无声通道上的通信永远无法进行,所以只能选择无通道且永远不会有默认情况下的块。” 为什么上面的块永远不会存在? [编辑:哦等一下,休息总是会发生在循环的第一次迭代之前,两者都是零] – voutasaurus