Common Concurrency Patterns
Fan-Out Pattern
Description
Distributes work across multiple workers, using channels for load balancing.
func fanOutPattern(jobs <-chan int, workerCount int) <-chan int {
results := make(chan int, workerCount)
for i := 0; i < workerCount; i++ {
go func() {
for job := range jobs {
results <- processJob(job)
}
}()
}
return results
}
Fan-In Pattern
Merging Multiple Channel Streams
graph TD
A[Channel 1] --> M[Merge Channel]
B[Channel 2] --> M
C[Channel 3] --> M
func fanInPattern(channels ...<-chan int) <-chan int {
merged := make(chan int)
var wg sync.WaitGroup
multiplex := func(ch <-chan int) {
defer wg.Done()
for v := range ch {
merged <- v
}
}
wg.Add(len(channels))
for _, ch := range channels {
go multiplex(ch)
}
go func() {
wg.Wait()
close(merged)
}()
return merged
}
Worker Pool Pattern
Concurrent Task Processing
type Task struct {
ID int
}
func workerPoolPattern(tasks <-chan Task, workerCount int) <-chan Result {
results := make(chan Result, workerCount)
for i := 0; i < workerCount; i++ {
go func() {
for task := range tasks {
result := processTask(task)
results <- result
}
}()
}
return results
}
Concurrency Patterns Comparison
Pattern |
Use Case |
Characteristics |
Fan-Out |
Distribute workload |
Parallel processing |
Fan-In |
Aggregate results |
Consolidate streams |
Worker Pool |
Controlled concurrency |
Limited parallel execution |
Cancellation and Context Pattern
func cancellationPattern(ctx context.Context) error {
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
resultCh := make(chan int)
go func() {
// Long-running task
select {
case <-ctx.Done():
return
case resultCh <- performTask():
}
}()
select {
case result := <-resultCh:
return processResult(result)
case <-ctx.Done():
return ctx.Err()
}
}
Pipeline Pattern
graph LR
A[Input] --> B[Stage 1]
B --> C[Stage 2]
C --> D[Stage 3]
D --> E[Output]
func pipelinePattern(input <-chan int) <-chan int {
output := make(chan int)
go func() {
defer close(output)
for v := range input {
processed := stage1(v)
transformed := stage2(processed)
output <- transformed
}
}()
return output
}
LabEx Concurrency Insights
At LabEx, we recommend mastering these patterns to build efficient and scalable concurrent applications.
Key Takeaways
- Choose appropriate patterns based on specific requirements
- Understand channel communication mechanics
- Implement proper synchronization and cancellation
- Balance concurrency with resource management