我有一个函数,给定一个切片和一个数组,将把切片的元素逐个发送到通道
package main
import (
"fmt"
)
var list1 = []string{"1", "2", "4"}
var list2 = []string{"11", "22", "44"}
func throw(ch chan string, list []string) {
for _, el := range list {
fmt.Println("Thrown ", el)
ch <- el
}
close(ch)
return
}
func main() {
c := make(chan string)
go throw(c, list1)
go throw(c, list2)
for i := range c {
fmt.Println("received ", i)
}
}
在某些时候,频道会关闭,但其中一个功能仍然需要向其发送数据。我该怎么处理?分离频道似乎是最合理的选择,但我希望两个数据都通过相同的频道。
答案 0 :(得分:4)
Go期望通道发送端的代码知道通道是否已关闭。因此代码就像你的代码片段,其中每个goroutine可以关闭频道而不考虑另一个是错误的。
一种解决方案是使用sync.WaitGroup
来协调每个goroutine何时完成,并让第三个goroutine执行关闭。因此,您要修改throw
函数,使其类似于:
func throw(ch chan string, list []string, wg *sync.WaitGroup) {
defer wg.Done()
// current body of function, without the close() call
}
并将生成goroutines的代码更改为以下内容:
var wg sync.WaitGroup
wg.Add(2)
go throw(c, list1, &wg)
go throw(c, list2, &wg)
go func() {
wg.Wait()
close(c)
}()
这样您的频道只会在其他两个goroutine完成后关闭。您可以在此处试验此示例的修改版本:http://play.golang.org/p/nUiwjGglgU