2014-08-28 4 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 ожидает, что код на отправляющей стороне канала узнает, был ли канал закрыт или нет. Таким образом, код, подобный вашему фрагменту, где каждый горутин может закрыть канал без учета другого, является ошибкой.

Одним из решений является использование sync.WaitGroup для координации при завершении каждого горутинга и выполнения третьего горутинга. Таким образом, вы бы изменить вашу 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) 
}() 

Таким образом, ваш канал будет закрыт только после того, как другой два гортани завершены. Вы можете поэкспериментировать с этой измененной версией вашего примера здесь: http://play.golang.org/p/nUiwjGglgU

+0

Или вы можете использовать ручной подсчет так, как это http://play.golang.org/p/Rwf8PI22U2 – RoninDev

+0

Это будет работать, если вы знали, сколько предметов ожидать от канал, да. Это может быть правдой на этом надуманном примере, но, конечно, это не общий случай. –

+0

Конечно! Все зависит от условий задания. Ваше решение более общее, поэтому я проголосовал за него – RoninDev

Смежные вопросы