Шаблоны fan-in и fan-out
Объединение нескольких каналов и распределение работы
«Шаблоны fan-in и fan-out» — бесплатный урок Go Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.
Что такое распределение
Распределение направляет работу из одного канала в несколько горутин, обеспечивая параллельную обработку. Каждый обработчик получает данные из одного и того же входного канала.
Пример распределения
Запустите N обработчиков, каждый из которых читает из общего канала заданий:
func fanOut(jobs <-chan Job, n int) {
for i := 0; i < n; i++ {
go func() {
for job := range jobs {
process(job)
}
}()
}
}Что такое сведение
Сведение объединяет несколько каналов в один, чтобы один потребитель мог читать результаты от множества производителей.
Сведение с помощью горутин
Запустите по одной горутине для каждого входного канала; каждая горутина будет передавать значения в общий выходной канал.
func fanIn(cs ...<-chan int) <-chan int {
out := make(chan int)
var wg sync.WaitGroup
for _, c := range cs {
wg.Add(1)
go func(ch <-chan int) {
defer wg.Done()
for v := range ch { out <- v }
}(c)
}
go func() { wg.Wait(); close(out) }()
return out
}Сведение с помощью select
Для фиксированного числа входных каналов цикл select проще, чем отдельная горутина для каждого канала.
func merge(a, b <-chan int) <-chan int {
out := make(chan int)
go func() {
defer close(out)
for a != nil || b != nil {
select {
case v, ok := <-a: if !ok { a = nil } else { out <- v }
case v, ok := <-b: if !ok { b = nil } else { out <- v }
}
}
}()
return out
}Этап конвейера
Объедините распределение и сведение, чтобы построить этап конвейера: один входной канал, N параллельных обработчиков и один объединённый выходной канал.
func parallelStage(in <-chan Work, n int) <-chan Result {
outs := make([]<-chan Result, n)
for i := 0; i < n; i++ {
outs[i] = worker(in)
}
return fanIn(outs...)
}Корректное закрытие каналов
Канал закрывает отправитель; получатель обнаруживает закрытие с помощью формы получения с двумя значениями или перебирая канал в цикле. Никогда не закрывайте канал со стороны получателя.
for v := range in { // exits when in is closed
process(v)
}Координация с помощью WaitGroup
Используйте sync.WaitGroup, чтобы определить момент завершения всех обработчиков распределения, а затем закройте выходной канал, чтобы последующие потребители могли завершить работу.
Обратное давление
Используйте буферизованные каналы между этапами конвейера, чтобы сглаживать всплески. Размер буфера определяйте с учётом ожидаемой разницы задержек между производителем и потребителем.
out := make(chan Result, 100) // buffer absorbs burstsПередача ошибок
Оберните результаты в структуру, содержащую и значение, и ошибку, чтобы ошибки проходили через конвейер вместе с данными, не вызывая аварийного завершения.
type Result struct {
Value int
Err error
}Отмена через контекст
Передавайте контекст через этапы конвейера и проверяйте ctx.Done() на каждом этапе, чтобы весь конвейер останавливался после отмены.
case <-ctx.Done():
return ctx.Err()Проверка знаний
В шаблоне сведения что закрывает объединённый выходной канал?
Итоги: сведение и распределение
Главное:
- Распределение: несколько обработчиков читают из одного канала
- Сведение: по одной горутине для каждого источника объединяют данные в один выходной канал
- WaitGroup координирует закрытие объединённого канала
- Для отмены используйте контекст, а для обратного давления — буферизованные каналы
Часто задаваемые вопросы
Урок «Шаблоны fan-in и fan-out» бесплатный?
Да — полный текст урока «Шаблоны fan-in и fan-out» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.
Чему я научусь в уроке «Шаблоны fan-in и fan-out»?
Объединение нескольких каналов и распределение работы Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Go Academy?
Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Шаблоны fan-in и fan-out»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Go Academy?
Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Оператор select
- Тайм-ауты и тикеры
- Шаблоны fan-in и fan-out
- Шаблон пула работников