Вопрос проверяет понимание паттернов конкурентности в Go для эффективного управления goroutine и каналами.
Fan-out и fan-in — это два взаимодополняющих паттерна конкурентности в Go, которые позволяют эффективно распределять работу между несколькими goroutine и собирать результаты. Fan-out означает разделение потока данных на несколько параллельных обработчиков, а fan-in — объединение результатов из нескольких источников в один поток.
При fan-out одна goroutine (обычно продюсер) отправляет данные в несколько каналов или запускает несколько worker goroutine, которые обрабатывают данные параллельно. Это полезно, когда задача может быть разбита на независимые подзадачи, которые можно выполнять одновременно.
func fanOut(input <-chan int, workers int) []<-chan int {
channels := make([]<-chan int, workers)
for i := 0; i < workers; i++ {
ch := make(chan int)
go func() {
for val := range input {
ch <- val * 2 // обработка
}
close(ch)
}()
channels[i] = ch
}
return channels
}При fan-in несколько goroutine отправляют данные в один общий канал, который читается одной goroutine (потребителем). Это позволяет объединить результаты параллельной работы в единый поток для дальнейшей обработки.
func fanIn(channels ...<-chan int) <-chan int {
out := make(chan int)
var wg sync.WaitGroup
for _, ch := range channels {
wg.Add(1)
go func(c <-chan int) {
defer wg.Done()
for val := range c {
out <- val
}
}(ch)
}
go func() {
wg.Wait()
close(out)
}()
return out
}Эти паттерны часто используются вместе: сначала fan-out для распараллеливания обработки данных (например, обработка HTTP-запросов, вычисления), затем fan-in для сбора результатов. Это основа для построения конвейеров обработки данных (pipeline) в Go.
Вывод: Fan-out и fan-in — ключевые паттерны для эффективного использования goroutine и каналов, позволяющие создавать масштабируемые и производительные конкурентные приложения в Go.