Ответ
Да, оператор range
можно использовать для итерации по значениям, поступающим из канала. Цикл for ... range
автоматически считывает данные из канала до тех пор, пока он не будет закрыт.
Принцип работы:
- Цикл блокируется, ожидая поступления нового значения в канал.
- Когда значение приходит, оно присваивается переменной итерации, и тело цикла выполняется.
- Это повторяется для каждого значения.
- Когда канал закрывается (
close(channel)
) и все значения из его буфера прочитаны, циклrange
завершается.
Пример:
package main
import "fmt"
func main() {
ch := make(chan int, 3) // Буферизованный канал
go func() {
defer close(ch) // Важно закрыть канал, чтобы range завершился
for i := 1; i <= 5; i++ {
ch <- i
}
}()
// Цикл будет читать из канала, пока он не будет закрыт и пуст
for value := range ch {
fmt.Println("Получено:", value) // Выведет от 1 до 5
}
fmt.Println("Канал закрыт, цикл завершен.")
}
Ключевые моменты:
- Deadlock: Если вы используете
range
на канале, который никогда не закроется, а все отправляющие горутины завершились, программа впадет в deadlock, так как цикл будет вечно ждать новых данных. - Nil-канал: Использование
range
наnil
-канале приведет к вечной блокировке, даже если канал никто не собирается закрывать (так какnil
-канал всегда блокирует операции чтения и записи).