我想知道go语言是否允许同时检查多个频道 。
以下是我正在尝试做的一个有点人为的例子。 (实际的原因是看看我是否可以在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)
}
这不会如图所示编译。它只能通过检查一个通道来编译,但如果该通道准备好但另一个通道没有准备就可以完全死锁。
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上的值准备就绪时,我不能提交任何一个分支:只有当所有值都准备就绪时。
答案 0 :(得分:1)
您无法同时在多个频道上进行选择。您可以做的是实现扇入模式,以便从多个渠道合并您的值。
基于代码的粗略示例可能如下所示:
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]
}
}
}
答案 1 :(得分:0)
您正在积累的两个不同对的单个频道可能有效:
package main
import "fmt"
func mynetPlus(a, b <-chan int, res chan<- int) {
for {
select {
case v1 := <-a:
v2 := <-b
res <- v1 + v2
case v2 := <-b:
v1 := <-a
res <- v1 + v2
}
}
}
func mynetMinus(c, d <-chan int, res chan<- int) {
for {
select {
case v1 := <-c:
v2 := <-d
res <- v1 + v2
case v2 := <-d:
v1 := <-c
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 mynetPlus(a, b, res)
go mynetMinus(c, d, res)
a <- 5
c <- 5
d <- 7
//a <- 5
b <- 7
fmt.Println(<-res)
fmt.Println(<-res)
}