2014-08-28 85 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

相關問題