選擇與在不同通道上接收的多個并發協程:在邏輯或性能上有區別嗎?
我的問題更普遍的是關于在 Go 中實作“扇入”方案。在我看來,使用“選擇”的方案在任意大量通道(大通道陣列)的情況下不起作用。
請參閱以下示例中的 receive() 和 receive2() 。
receive2() 函式是否過于復雜?矯枉過正?
為什么選擇公式被認為更慣用?
package main
import (
"fmt"
"time"
)
func main() {
var ch1 = make(chan int)
var ch2 = make(chan int)
send(ch1, ch2)
//receive(ch1, ch2)
receive2(ch1, ch2)
time.Sleep(3 * time.Second)
}
func send(ch1 chan int, ch2 chan int) {
go func() {
for i := 0; i < 10; i {
ch1 <- i
}
close(ch1)
}()
go func() {
for i := 0; i < 10; i {
ch2 <- i
}
close(ch2)
}()
}
func receive(ch1 chan int, ch2 chan int) {
go func() {
for item := range ch1 {
fmt.Printf("1: %d\n", item)
}
}()
go func() {
for item := range ch2 {
fmt.Printf("2: %d\n", item)
}
}()
}
func receive2(ch1 chan int, ch2 chan int) {
for {
select {
case x, ok := <-ch1:
fmt.Println("ch1", x, ok)
if !ok {
ch1 = nil
}
case x, ok := <-ch2:
fmt.Println("ch2", x, ok)
if !ok {
ch2 = nil
}
}
if ch1 == nil && ch2 == nil {
break
}
}
}
uj5u.com熱心網友回復:
您的實施不是扇入。扇入將多個通道的結果收集到一個通道中。像這樣,您可以在單個out通道上接收所有值。
func fanIn(in ...chan int) chan int {
out := make(chan int)
for _, c := range in {
go func(i chan int) {
for v := range i {
out <- v
}
}(c)
}
return out
}
在您的實作中,第一個receive()只是從 N 個通道同時接收,彼此獨立。它可以被重寫為接受一個可變引數,并且看起來更像是一個實際的扇入:
func receive(cs ...chan int) {
for i, cN := range cs {
go func(i int, c chan int) {
for item := range c {
fmt.Printf("%d: %d\n", i, item)
}
}(i, cN)
}
}
的receive2(),而不是本質上是連續的,不會結垢,因為你會寫一個case為每個通道,和&&他們一起知道什么時候打破回圈。該&&可與被改寫sync.WaitGroup,但你還是會處理在每次迭代中只有一個專案(隨機的,是準備接收的病例中)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/358282.html
