两个例程在同一个频道上进行通信

时间:2014-08-28 02:30:55

标签: concurrency go channel goroutine

我有一个函数,给定一个切片和一个数组,将把切片的元素逐个发送到通道

Link to playground

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)
    }
}

在某些时候,频道会关闭,但其中一个功能仍然需要向其发送数据。我该怎么处理?分离频道似乎是最合理的选择,但我希望两个数据都通过相同的频道。

1 个答案:

答案 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