我想知道 go 语言是否允许检查多个 channel 是否准备就绪同时。
这是我正在尝试做的一个有点人为的例子。 (实际原因是看我能不能在go中原生实现petrinets)
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)
}
这不会像显示的那样编译。它可以通过仅检查一个 channel 来编译,但如果该 channel 准备就绪但另一个 channel 未准备好,它可能会死锁。
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)
}
在一般情况下,我可能有多个案例在同一个 channel 上等待,例如
case v1, v2 := <-a, <-b:
...
case v1, v2 := <-a, <-c:
...
所以当 channel a 上的值准备就绪时,我不能提交到任何一个分支:只有当所有值都准备好时。
最佳答案
您不能同时选择多个 channel 。您可以做的是实现扇入模式,以从多个 channel 整合您的值(value)观。
基于您的代码的粗略示例可能如下所示:
func collect(ret chan []int, chans ...<-chan int) {
ints := make([]int, len(chans))
for i, c := range chans {
ints[i] = <-c
}
ret <- ints
}
func mynet(a, b, c, d <-chan int, res chan<- int) {
set1 := make(chan []int)
set2 := make(chan []int)
go collect(set1, a, b)
go collect(set2, c, d)
for {
select {
case vs := <-set1:
res <- vs[0] + vs[1]
case vs := <-set2:
res <- vs[0] + vs[1]
}
}
}
关于go - 检查准备就绪的同步 channel ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31707158/