我有以下代码:
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
stuff := fanIn(
generator(4, 5, 6, 7),
generator(1, 2, 6, 3, 7),
generator(12, 15, 33, 40, 10),
generator(18, 13, 20, 40, 15),
generator(100, 200, 64000, 3121, 1237),
)
for v := range stuff {
fmt.Println(v)
}
fmt.Println(t.Sub(time.Now()))
}
func generator(nums ...int) <-chan int {
out := make(chan int, 10)
go func() {
defer close(out)
for _, v := range nums {
out <- v
}
}()
return out
}
func fanIn(in ...<-chan int) <-chan int {
out := make(chan int, 10)
for _, v := range in {
go func(ch <-chan int) {
for val := range ch {
go func(c int) { out <- c }(val)
}
}(v)
}
return out
}
导致第18行出现死锁:
for v := range stuff {...}
问题(我认为)是我不会推迟返回只读频道的fanIn函数的关闭。我不知道何时推迟它,因为它需要等待多个goroutine的结束才能完成。
解决这种僵局的惯用方法是什么?这段代码是不是惯用的?
谢谢!
答案 0 :(得分:3)
您对错误导致fanIn
频道错误的原因是正确的。您可以使用sync.WaitGroup
来解决问题:
func fanIn(in ...<-chan int) <-chan int {
// use a WaitGroup here
var wg sync.WaitGroup
out := make(chan int, 10)
for _, v := range in {
wg.Add(1)
go func(ch <-chan int) {
defer wg.Done()
for val := range ch {
out <- val
}
}(v)
}
// wait for wait groups to finish in another goroutine
go func() {
wg.Wait()
close(out)
}()
return out
}