Конструкция for v := range ch читает значения из канала до тех пор, пока он не будет закрыт. Это самый идиоматичный способ потребления данных из канала.
ch := make(chan int)
go func() {
for i := 0; i < 5; i++ {
ch <- i
}
close(ch) // без этого range заблокируется навсегда
}()
for v := range ch {
fmt.Println(v) // 0, 1, 2, 3, 4
}
// цикл завершится после close(ch)
for range по каналу эквивалентен:
for {
v, ok := <-ch
if !ok {
break // канал закрыт
}
fmt.Println(v)
}
func produce(ch chan<- string) {
defer close(ch)
for _, url := range urls {
ch <- fetch(url)
}
}
func consume(ch <-chan string) {
for result := range ch {
process(result)
}
}
Важно: если забыть close(ch), цикл range заблокируется навсегда - это утечка горутины. Закрывать канал должен только отправитель.