在使用以下内容测试某些代码时:
// ch := make(chan error)
for {
select {
case <- ch:
println("here")
}
}
Run Code Online (Sandbox Code Playgroud)
我注意到如果我不添加default代码块:
for {
select {
case <- ch:
println("here")
default:
}
}
Run Code Online (Sandbox Code Playgroud)
如果块是必需的,那么就可以使用range,例如:
for {
for _ = range <- ch {
println("here")
}
}
Run Code Online (Sandbox Code Playgroud)
或者select在range这种情况下使用结束有什么不同/优势?
小智 7
1-当您处理一个频道时,可以使用for,
考虑这个工作代码(The Go Playground):
package main
import "fmt"
func main() {
ch := make(chan int, 2)
ch <- 1
ch <- 2
close(ch)
for range ch {
}
fmt.Println("Done.")
}
Run Code Online (Sandbox Code Playgroud)
这将清空频道.
注意:您应该close使用频道,或者您应该使用breakstatement来完成该循环.
2-当您处理更多可能使用的频道时select,如此(The Go Playground):
for {
select {
case <-pause:
fmt.Println("pause")
select {
case <-play:
fmt.Println("play")
case <-quit:
wg.Done()
return
}
case <-quit:
wg.Done()
return
default:
work()
}
}
Run Code Online (Sandbox Code Playgroud)
3-使用零和封闭的通道(The Go Playground):
package main
import "fmt"
func main() {
var quit chan struct{} // nil
select {
case <-quit:
fmt.Println("1")
default:
fmt.Println("2") // This runs
}
quit = make(chan struct{}, 1)
select {
case <-quit:
fmt.Println("10")
default:
fmt.Println("20") // This runs
}
quit <- struct{}{} // send
select {
case <-quit:
fmt.Println("100") // This runs
default:
fmt.Println("200")
}
close(quit)
select {
case <-quit:
fmt.Println("1000") // This runs
default:
fmt.Println("2000")
}
select {
case <-quit:
fmt.Println("10000") // This runs
default:
fmt.Println("20000")
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
2
20
100
1000
10000
Run Code Online (Sandbox Code Playgroud)
"select"语句选择一组可能的发送或接收操作中的哪一个将继续.它看起来类似于"switch"语句,但所有情况都涉及通信操作.
具有RecvStmt的情况可以将RecvExpr的结果分配给一个或两个变量,这些变量可以使用短变量声明来声明.RecvExpr必须是(可能是带括号的)接收操作.最多只能有一个默认情况,它可能出现在案例列表中的任何位置.
执行"select"语句分几步进行:
对于语句中的所有情况,接收操作的通道操作数以及发送语句的通道和右侧表达式在输入"select"语句后按源顺序精确计算一次.结果是一组要接收或发送的通道,以及要发送的相应值.无论选择哪种(如果有的话)通信操作进行,评估中的任何副作用都将发生.尚未评估具有短变量声明或赋值的RecvStmt左侧的表达式.如果一个或多个通信可以继续,则可以通过统一的伪随机选择来选择可以继续的单个通信.否则,如果存在默认情况,则选择该情况.如果没有默认情况,则"select"语句将阻塞,直到至少一个通信可以继续.除非所选择的情况是默认情况,否则执行相应的通信操作.如果所选案例是具有短变量声明或赋值的RecvStmt,则评估左侧表达式并分配接收值(或多个值).执行所选案例的语句列表.由于nil通道上的通信永远不会进行,因此只选择nil通道并且永远不会出现默认情况.
在你的情况下,似乎一个简单的循环就足够了:
for _ = range ch {
fmt.Println("drain")
}
Run Code Online (Sandbox Code Playgroud)
如果您有多个goroutine 需要处理,则需要选择。该游览有range 和 close的示例。
另一种情况select是幂等通道关闭:https://play.golang.org/p/_Ol42BvuuS。