Del*_*ace 86
我知道从通道读取的唯一非阻塞操作是在具有默认情况的选择块内:
select {
case x, ok := <-ch:
if ok {
fmt.Printf("Value %d was read.\n", x)
} else {
fmt.Println("Channel closed!")
}
default:
fmt.Println("No value ready, moving on.")
}
Run Code Online (Sandbox Code Playgroud)
备注以前的答案:接收运营商本身就是现在阻塞操作,如围棋1.0.3.该规范已被修改.请在这里尝试阻止(死锁)
如果你经常这样做,那么它可能不是一个很棒的设计,如果没有任何东西可以从频道中读取,你可能最好再产生另一个goroutine去做你计划做的任何工作.Go的通道的同步/阻塞特性使代码更容易阅读和推理,而调度程序和廉价的goroutine意味着异步调用是不必要的,因为等待goroutines占用非常少的资源.
你没有,至少不是同步(无缓冲)通道.如果没有要求从通道中获取值,则无法判断值是否在等待.
对于缓冲通道,从技术上讲,您可以使用len函数来执行您所描述的操作,但实际上,您确实不应该这样做.你的技术无效.
原因是它代表了竞争条件.给定通道ch,你的goroutine可能会看到len(ch)> 0并得出结论是有值等待.但是,它无法得出结论,它可以在不阻塞的情况下从通道读取 - 另一个goroutine可能会在您检查len和接收操作运行的时间之间清空通道.
出于您所描述的目的,使用select作为Ripounet显示的默认情况.
警告:这不再准确,请参阅下面的答案.
来自文档:
如果在表单的赋值或初始化中使用了接收表达式
Run Code Online (Sandbox Code Playgroud)x, ok = <-ch x, ok := <-ch var x, ok = <-ch
接收操作变为非阻塞.如果操作可以继续,则布尔变量ok将被设置为true并且值存储在x中; 否则ok设置为false,x设置为其类型的零值