Fan In vs Fan Out Pattern in Go: Key Differences and Usage
Fan Out means starting multiple goroutines to perform tasks concurrently, spreading work out. Fan In means combining results from multiple goroutines into a single channel to collect outputs.Quick Comparison
This table summarizes the main differences between Fan In and Fan Out patterns in Go concurrency.
| Aspect | Fan Out | Fan In |
|---|---|---|
| Purpose | Distribute work to multiple goroutines | Combine results from multiple goroutines |
| Channels | Multiple goroutines send to different channels | Multiple channels merged into one |
| Concurrency | Increases parallelism by spawning goroutines | Synchronizes and collects outputs |
| Use case | Parallelize tasks like fetching data | Aggregate results like merging streams |
| Complexity | Simple to start goroutines | Requires careful channel merging |
| Example | Starting workers for tasks | Merging worker outputs |
Key Differences
Fan Out is about spreading work across many goroutines to run tasks in parallel. For example, if you have many jobs, you create multiple goroutines so they can work at the same time, speeding up processing.
Fan In is the opposite: it collects results from many goroutines into a single channel. This helps you gather all outputs in one place to process or return them together.
While Fan Out focuses on creating concurrency by launching goroutines, Fan In focuses on synchronizing and merging data streams from those goroutines. Both patterns often work together in Go programs to efficiently handle concurrent tasks.
Code Comparison
This example shows Fan Out where multiple goroutines perform work concurrently and send results to separate channels.
package main import ( "fmt" "time" ) func worker(id int, ch chan<- string) { time.Sleep(time.Duration(id) * 100 * time.Millisecond) ch <- fmt.Sprintf("worker %d done", id) } func main() { channels := make([]chan string, 3) for i := 0; i < 3; i++ { channels[i] = make(chan string) go worker(i+1, channels[i]) } for i, ch := range channels { result := <-ch fmt.Printf("Result from channel %d: %s\n", i+1, result) } }
Fan In Equivalent
This example shows Fan In where results from multiple goroutines are merged into a single channel for easy collection.
package main import ( "fmt" "time" ) func worker(id int, ch chan<- string) { time.Sleep(time.Duration(id) * 100 * time.Millisecond) ch <- fmt.Sprintf("worker %d done", id) } func fanIn(channels ...chan string) chan string { merged := make(chan string) for _, ch := range channels { go func(c chan string) { for msg := range c { merged <- msg } }(ch) } return merged } func main() { channels := make([]chan string, 3) for i := 0; i < 3; i++ { channels[i] = make(chan string, 1) go worker(i+1, channels[i]) } merged := fanIn(channels...) for i := 0; i < 3; i++ { fmt.Println(<-merged) } }
When to Use Which
Choose Fan Out when you want to speed up processing by running many tasks at the same time using multiple goroutines. It helps when you have many independent jobs to do.
Choose Fan In when you need to collect or merge results from multiple goroutines into one place. It is useful to gather outputs for further processing or to return a combined result.
Often, you use both together: Fan Out to start concurrent work, and Fan In to collect all results efficiently.