2014-08-28 54 views
1

我有,给定一个切片和阵列,将由一个两个例程在相同的信道上进行通信

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

切片的元素发送到所述信道的一个。在一些函数指出通道关闭,但其中一个功能仍然需要向其发送数据。我该如何处理?制作分离频道似乎是最合理的选择,但我希望两个数据都能通过同一频道。

回答

4

Go期望通道发送端的代码知道通道是否已关闭。因此,像你的代码片段一样,每个goroutine可以关闭该通道而不考虑另一个通道的代码就是bug。

一个解决方案是在每个goroutine完成时使用sync.WaitGroup进行协调,并让第三个goroutine执行关闭。所以,你会修改throw功能看起来是这样的:

func throw(ch chan string, list []string, wg *sync.WaitGroup) { 
    defer wg.Done() 
    // current body of function, without the close() call 
} 

,并更改滋生的够程以下代码:

var wg sync.WaitGroup 
wg.Add(2) 
go throw(c, list1, &wg) 
go throw(c, list2, &wg) 
go func() { 
    wg.Wait() 
    close(c) 
}() 

这样,你的渠道只会对方后关闭两个门房完成。您可以在这里试验这个示例的修改版本:http://play.golang.org/p/nUiwjGglgU

+0

或者您可以使用像这样的手动计数http://play.golang.org/p/Rwf8PI22U2 – RoninDev 2014-08-28 05:41:19

+0

如果您知道有多少物品可以期望渠道,是的。在这个人为的例子中可能是这样,但肯定不是一般情况。 – 2014-08-28 06:38:55

+0

当然!这完全取决于任务的条件。你的解决方案更一般,所以我投了票 – RoninDev 2014-08-28 06:48:28

相关问题