鉴于此代码模拟使用扇入模式获取 3 个 URL 的某些网站内容,并覆盖压缩频道:https : //play.golang.org/p/MSkRI7x4vz
for s := range r {
println(s)
}
Run Code Online (Sandbox Code Playgroud)
这很好用,但我想使用整体超时信号通道,所以我尝试在这样的 for 循环中使用选择:https : //play.golang.org/p/LjDoIc0j-z
totalTimeout := time.After(300 * time.Millisecond)
loop:
for {
select {
case s := <-r:
fmt.Println(s)
case <-totalTimeout: // signaling usage of a channel
fmt.Println("Timed out")
break loop
}
}
}
Run Code Online (Sandbox Code Playgroud)
这表现得不好:在输入通道关闭后,来自扇入的压缩通道被关闭。但是现在读取零值直到超时有效发生。当我阅读http://www.tapirgames.com/blog/golang-channel或规范https://golang.org/ref/spec#Close 时,似乎从关闭的频道接收“从不阻塞”并因此返回零值。我只能猜测,范围检测关闭,选择不能,因为它的条件是从本身的通道读取。
我可以这样爆发
case s := <-r:
if s == "" {
break loop
}
fmt.Println(s)
Run Code Online (Sandbox Code Playgroud)
是否有另一种方法来停止获取空值,或者这是在 for 循环中使用 select 的正确惯用方法?
在接收到通道中的所有元素后,在关闭的通道上接收产生零值。
使用两个值接收来检测通道何时关闭和从循环中断开。当通道由于通道关闭而产生零值时,第二个值为 false。
for {
select {
case s, ok := <-r:
if !ok {
break loop
}
fmt.Println(s)
case <-totalTimeout: // signaling usage of a channel
fmt.Println("Timed out")
break loop
}
}
Run Code Online (Sandbox Code Playgroud)