【发布时间】:2021-10-11 10:02:05
【问题描述】:
我创建了以下简单程序来测试使用通道的扇入扇出模式。它所做的是生成一些 go 例程来计算来自输入通道的数字的平方并将平方发送到输出通道。然后将所有输出通道合并到一个通道中以打印main中的正方形。
func calculateSquare(in <-chan int) <-chan int {
out := make(chan int)
go func() {
for num := range in {
fmt.Printf("Receving num %v\n", num)
out <- num * num
fmt.Printf("Sending square %v\n", num * num)
}
fmt.Println("Closing out")
close(out)
}()
return out
}
func fanOut(in <-chan int, workerCount int) []<-chan int {
outs := make([]<-chan int, 0, workerCount)
for i := 0 ; i < workerCount ; i++ {
outs = append(outs, calculateSquare(in))
}
return outs
}
func fanIn(outs []<-chan int) <-chan int {
var wg sync.WaitGroup
merge := make(chan int)
for _, out := range outs {
wg.Add(1)
go func() {
for result := range out {
merge <- result
}
wg.Done()
}()
}
go func() {
wg.Wait()
fmt.Println("Closing merge")
close(merge)
}()
return merge
}
func main() {
in := make(chan int)
go func() {
for i := 0 ; i < 4 ; i++ {
fmt.Printf("Sending num %v\n", i)
in <- i
}
close(in)
}()
outs := fanOut(in, 5)
merge := fanIn(outs)
for num := range merge {
fmt.Printf("Final square %v\n", num)
}
}
在main 函数中,我将 4 个数字 0 -> 3 发送到输入通道,我希望在控制台中看到 4 个正方形。然而,当我运行程序时,即使输出有点波动,但我从未在控制台中看到打印过 4 个平方数。
下面是我看到的示例输出。
Sending num 0
Sending num 1
Sending num 2
Sending num 3
Closing out
Receving num 0
Receving num 1
Receving num 2
Sending square 4
Closing out
Receving num 3
Final square 4
Closing merge
如果有人能向我解释为什么打印了Receving num 1 而Sending square 1 永远不会出现,我将不胜感激。另外,如果Sending square 1没有打印出来,output这个通道是怎么关闭的。我只看到 2 个Closing out,但是,我正在合并结果的等待组结束了它的Wait()。
我一定是哪里做错了。
【问题讨论】:
-
运行
go vet(或运行任何测试,然后运行go vet),你会看到问题:golang.org/doc/faq#closures_and_goroutines -
@JimB 谢谢你的指点。几天前我读到了这个常见的错误,但我仍然犯了。多么新手的错误:D