> Как реализовать паттерн fan-out fan-in в Go с использованием горутин? (Go)
Уровень: senior · Роль: backend · Категория: Технические вопросы
Компании: Axel Pro
Стек: Go
> Пример ответа
Для реализации паттерна fan-out fan-in в Go создаются несколько горутин-воркеров (fan-out), которые обрабатывают данные из общего входного канала, и одна горутина-агрегатор (fan-in), собирающая результаты в единый выходной канал.
Пример реализации:
GOpackage mainimport ("fmt""sync")// fanOut запускает n воркеров, читающих из входного каналаfunc fanOut(input <-chan int, n int) []<-chan int {channels := make([]<-chan int, n)for i := 0; i < n; i++ {ch := make(chan int)channels[i] = chgo func(workerID int, out chan<- int) {for val := range input {// Обработка данных (например, умножение на 2)result := val * 2fmt.Printf("Worker %d обработал: %d -> %d\n", workerID, val, result)out <- result}close(out)}(i, ch)}return channels}// fanIn собирает данные из нескольких каналов в одинfunc fanIn(channels ...<-chan int) <-chan int {out := make(chan int)var wg sync.WaitGroupwg.Add(len(channels))for _, ch := range channels {go func(c <-chan int) {defer wg.Done()for val := range c {out <- val}}(ch)}// Закрываем выходной канал после завершения всех воркеровgo func() {wg.Wait()close(out)}()return out}func main() {// Создаём входной каналinput := make(chan int)// Запускаем fan-out с 3 воркерамиworkerChannels := fanOut(input, 3)// Запускаем fan-in для сбора результатовresults := fanIn(workerChannels...)// Отправляем данныеgo func() {for i := 1; i <= 5; i++ {input <- i}close(input)}()// Читаем результатыfor res := range results {fmt.Printf("Результат: %d\n", res)}}
Ключевые моменты:
- Fan-out: несколько горутин читают из одного канала, Go автоматически распределяет сообщения между ними.
- Fan-in: используется
sync.WaitGroupдля ожидания завершения всех воркеров, после чего закрывается выходной канал. - Важно закрывать каналы корректно, чтобы избежать deadlock'ов.
- Паттерн эффективен для параллельной обработки независимых задач, например, обработки запросов или вычислений.
> Похожие задачи по backend
В чем различия между стеком и хипом в Go
Уровень: seniorКатегория: Технические вопросы
Компания: Т-Банк
Стек: Go
Что происходит в программе при отсутствии доступной памяти
Уровень: middleКатегория: Технические вопросы
Компания: Avito
Стек: Go
Что такое селективность индекса и почему не всегда индекс используется?
Уровень: juniorКатегория: Технические вопросы
Компания: Сбер, Employcity
Стек: Go
Что происходит с внешним сервисом при повторных обращениях во время сбоя
Уровень: seniorКатегория: Технические вопросы
Компания: Wildberries
Стек: Go
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью