Правильный способ закрыть канал - PullRequest
0 голосов
/ 18 декабря 2018

Я хочу иметь кучу программ, которые будут получать некоторую информацию со многих серверов.Я упрощаю приведенный ниже код, чтобы он был более читабельным.Кажется, он работает отлично, но паникует после того, как все задачи были выполнены, так как я никогда не закрываю канал.Дело в том, что я не уверен, , где Я должен закрыть то же самое.

Мне нужна ваша помощь в:

  • Скажите мне, где в коде я должен бытьзакрытие канала.
  • Скажите, выглядит ли общая логика этого кода идиоматически правильной.

мой код

func main() {
        ch := make(chan string)


        for i:= 0; i < 10 ; i++ {
                go func(c chan <- string,t int){
                        time.Sleep( time.Duration(rand.Intn(3000)) * time.Millisecond )
                        c <- strconv.Itoa(t) + " : Done " + strconv.Itoa(rand.Intn(3000))
                }(ch,i)
        }
        for val := range ch {
                fmt.Println(val)

        }
}

output

$ go run test_channels.go
0 : Done 1694
6 : Done 511
3 : Done 162
2 : Done 89
8 : Done 2728
5 : Done 1274
1 : Done 2211
9 : Done 1445
4 : Done 2237
7 : Done 1106
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
        /home/matias/projects/src/github.com/matias/test/test_channels.go:22 +0x138
exit status 2

1 Ответ

0 голосов
/ 18 декабря 2018

Если в канале есть один отправитель, этот отправитель обычно отвечает за закрытие канала в случае необходимости.Помните, что закрытие канала не требуется для очистки, это только в том случае, если вам нужно сообщить о том, что канал закрыт.

При наличии нескольких отправителей вам необходимо согласовать со всеми из них завершение, которое выможно сделать с sync.waitGroup

ch := make(chan string)
var wg sync.WaitGroup

for i := 0; i < 10; i++ {
    wg.Add(1)
    go func(c chan<- string, t int) {
        defer wg.Done()
        time.Sleep(time.Duration(rand.Intn(3000)) * time.Millisecond)
        c <- strconv.Itoa(t) + " : Done " + strconv.Itoa(rand.Intn(3000))
    }(ch, i)
}

go func() {
    wg.Wait()
    close(ch)
}()

https://play.golang.org/p/ViOtMHbi43C

...