go 言語で複数のチャネルが同時に準備されているかどうかを確認できるかどうかを知りたいです。
これは、私がやろうとしていることのやや不自然な例です。(実際の理由は、ペトリネットを go でネイティブに実装できるかどうかを確認するためです)
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)
}
これは、示されているようにコンパイルされません。1 つのチャネルをチェックするだけでコンパイルすることができますが、そのチャネルの準備ができていて、もう 1 つのチャネルの準備ができていない場合、自明にデッドロックする可能性があります。
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 で値の準備ができている場合は、どちらのブランチにもコミットできません。すべての値の準備ができている場合のみです。