Как зациклить на буферизованном канале без блокировки?

Мне интересно, как я могу слить / закрыть буферизованные каналы, чтобы не попасть в тупик? Я использую диапазон для обхода каналов, но кажется, что они "читаются", но не закрываются, как небуферизованные каналы.

package main

func main() {

    cp := 2
    ch := make(chan string, cp)

    for i := 0; i < cp; i++ {
        go send(ch)
    }
    go send(ch)

    for lc := range ch {
        print(lc)

    }

}

func send(ch chan string) {

    ch <- "hello\n"

}

Играть

1 ответ

Решение

Вы можете закрыть каналы, используя close() встроенный Это должно быть вызвано после того, как вся ваша параллельная обработка сделана. То, как вы это делаете, зависит от того, что вы хотите сделать.

В вашей текущей архитектуре кажется, что вы должны установить глобальное состояние, которое отслеживает все ваши процессы и определяет, что последний завершен. Такое состояние может быть достигнуто с помощью sync.WaitGroup например.

func send(c chan string, wg *sync.WaitGroup) {
    defer wg.Done()
    // ...
}

wg := &sync.WaitGroup{}

for i := 0; i < cp; i++ {
    wg.Add(1)
    go send(ch, wg)
}
wg.Add(1)
go send(ch, wg)

wg.Wait()
close(ch)

for e := range(ch) {
    // ...
}

Обратите внимание, что закрытие канала и последующая итерация по нему даст вам только те элементы, которые находятся в очереди в канале. Это означает, что любая процедура, которая хотела поместить значение в канал, не может сделать это больше, так как канал закрыт.

Другие вопросы по тегам