0
0
GoComparisonIntermediate · 4 min read

Fan In vs Fan Out Pattern in Go: Key Differences and Usage

In Go, 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.

AspectFan OutFan In
PurposeDistribute work to multiple goroutinesCombine results from multiple goroutines
ChannelsMultiple goroutines send to different channelsMultiple channels merged into one
ConcurrencyIncreases parallelism by spawning goroutinesSynchronizes and collects outputs
Use caseParallelize tasks like fetching dataAggregate results like merging streams
ComplexitySimple to start goroutinesRequires careful channel merging
ExampleStarting workers for tasksMerging 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.

go
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)
	}
}
Output
Result from channel 1: worker 1 done Result from channel 2: worker 2 done Result from channel 3: worker 3 done
↔️

Fan In Equivalent

This example shows Fan In where results from multiple goroutines are merged into a single channel for easy collection.

go
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)
	}
}
Output
worker 1 done worker 2 done worker 3 done
🎯

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.

Key Takeaways

Fan Out starts multiple goroutines to perform tasks concurrently, increasing parallelism.
Fan In merges results from multiple goroutines into a single channel for easy collection.
Use Fan Out to distribute work and Fan In to aggregate outputs in Go concurrency.
Both patterns often combine to handle concurrent tasks efficiently.
Careful channel management is needed to avoid deadlocks when using Fan In.