Канал передаёт значения
Канал передаёт типизированные значения между горутинами. Операция отправки записывается как ch <- value, получение — как value := <-ch. У небуферизированного канала отправитель ждёт, пока получатель будет готов принять значение; это синхронная передача.
Буферизированный канал создают с ёмкостью, например make(chan int, 2). Он принимает до двух ещё не прочитанных значений. После заполнения следующая отправка блокируется, пока получатель не освободит место. «Буферизированный» не означает «неблокирующий при любом числе отправок».
Ключевое слово select ждёт готовности одной из перечисленных операций отправки или получения. Если готовы несколько веток, выбирается одна из них без приоритета; нельзя считать, что всегда сработает первая ветка. Для выбора с таймаутом часто добавляют ветку с каналом таймера. Канал закрывает отправитель, когда новых значений больше не будет. Получение из закрытого канала сразу возвращает нулевое значение и ok == false.
Пример
package main
import (
"fmt"
"sort"
)
func publish(values ...int) <-chan int {
items := make(chan int, len(values))
go func() {
defer close(items)
for _, value := range values {
items <- value
}
}()
return items
}
func main() {
left := publish(8, 2)
right := publish(7, 3)
values := make([]int, 0, 4)
for left != nil || right != nil {
select {
case value, ok := <-left:
if !ok {
left = nil
continue
}
values = append(values, value)
case value, ok := <-right:
if !ok {
right = nil
continue
}
values = append(values, value)
}
}
sort.Ints(values)
fmt.Println(values)
}
Каждый производитель владеет своим каналом и закрывает его после отправки двух значений. Ёмкость совпадает с числом отправок, поэтому производитель может завершиться, не ожидая, когда основная функция приступит к чтению. После заполнения такого буфера дополнительная отправка уже ждала бы получателя.
В цикле select получает значение из любого готового канала. Когда один закрывается, присваивание nil отключает его ветку: операция получения из nil-канала никогда не готова. После завершения обоих потоков сортировка устраняет неопределённость порядка выбора и программа печатает [2 3 7 8].