【发布时间】:2015-10-20 19:55:14
【问题描述】:
我想知道 go 语言是否允许同时检查多个通道是否准备就绪。
这是我正在尝试做的一个有点做作的例子。 (实际原因是看能不能在go中原生实现petrinet)
package main
import "fmt"
func mynet(a, b, c, d <-chan int, res chan<- int) {
for {
select {
case v1, v2 := <-a, <-b:
res <- v1+v2
case v1, v2 := <-c, <-d:
res <- v1-v2
}
}
}
func main() {
a := make(chan int)
b := make(chan int)
c := make(chan int)
d := make(chan int)
res := make(chan int, 10)
go mynet(a, b, c, d, res)
a <- 5
c <- 5
d <- 7
b <- 7
fmt.Println(<-res)
fmt.Println(<-res)
}
这不会如图所示编译。它可以通过只检查一个通道来编译,但是如果该通道准备好而另一个通道没有准备好,它可能会很容易死锁。
package main
import "fmt"
func mynet(a, b, c, d <-chan int, res chan<- int) {
for {
select {
case v1 := <-a:
v2 := <-b
res <- v1+v2
case v1 := <-c:
v2 := <-d
res <- v1-v2
}
}
}
func main() {
a := make(chan int)
b := make(chan int)
c := make(chan int)
d := make(chan int)
res := make(chan int, 10)
go mynet(a, b, c, d, res)
a <- 5
c <- 5
d <- 7
//a <- 5
b <- 7
fmt.Println(<-res)
fmt.Println(<-res)
}
在一般情况下,我可能有多个案例在同一个频道上等待,例如
case v1, v2 := <-a, <-b:
...
case v1, v2 := <-a, <-c:
...
所以当通道 a 上的值准备好时,我不能提交到任一分支:只有当所有值都准备好时。
【问题讨论】:
-
不。如果
b尚未准备好,您可以在通道上进行非阻塞接收(使用select和一个接收案例和default)以不阻塞(但是您已经从@987654327 中获取了一个值@),并且您可以在缓冲通道上执行len()来推测性地检查缓冲区中有多少项目(尽管在您的接收执行之前这可能会改变)。