我有两个goroutines独立生成数据,每个数据都发送到一个频道.在我的主要goroutine中,我想在它们进入时消耗每个输出,但不关心它们进入的顺序.每个通道在耗尽其输出时将自行关闭.虽然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
}
}
Run Code Online (Sandbox Code Playgroud)
我能想到的最好的是以下内容(只是草拟,可能有编译错误):
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}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果您使用超过两个或三个频道,这看起来会变得难以维持.我所知道的唯一另一种方法是在switch语句中使用一个timout案例,该案例要么小到足以提前退出,要么在最终循环中注入太多停机时间.有没有更好的方法来测试select语句中的通道?
Ste*_*erg 91
您的示例解决方案不会很好.一旦其中一个关闭,它将始终可用于立即通信.这意味着你的goroutine永远不会屈服,其他渠道可能永远不会准备好.你会有效地进入无限循环.我发布了一个例子来说明这里的效果:http://play.golang.org/p/rOjdvnji49
那么,我该如何解决这个问题呢?零通道从未准备好进行通信.所以每次你遇到一个封闭的通道,你都可以忽略那个通道,确保它再也不会被选中.可运行的例子:http://play.golang.org/p/8lkV_Hffyj
for {
select {
case x, ok := <-ch:
fmt.Println("ch1", x, ok)
if !ok {
ch = nil
}
case x, ok := <-ch2:
fmt.Println("ch2", x, ok)
if !ok {
ch2 = nil
}
}
if ch == nil && ch2 == nil {
break
}
}
Run Code Online (Sandbox Code Playgroud)
至于害怕它变得笨拙,我认为不会.您很少有频道同时前往太多地方.这很少会出现,我的第一个建议只是处理它.将10个通道与nil进行比较的长if语句并不是尝试处理选择中的10个通道的最差部分.
Son*_*nia 24
在某些情况下关闭很好,但不是全部.我不会在这里使用它.相反,我只会使用完成频道:
for n := 2; n > 0; {
select {
case p := <-mins:
fmt.Println("Min:", p) //consume output
case p := <-maxs:
fmt.Println("Max:", p) //consume output
case <-done:
n--
}
}
Run Code Online (Sandbox Code Playgroud)
在操场上完成工作示例:http://play.golang.org/p/Cqd3lg435y
zzz*_*zzz 10
为什么不使用goroutines?随着您的频道关闭,整个事情变成了一个简单的范围循环.
func foo(c chan whatever, prefix s) {
for v := range c {
fmt.Println(prefix, v)
}
}
// ...
go foo(mins, "Min:")
go foo(maxs, "Max:")
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
34306 次 |
| 最近记录: |