Concurrent Select Patterns
Timeout Pattern
Implementing timeouts is a crucial pattern in concurrent programming. Go's select statement provides an elegant solution:
func timeoutExample() {
ch := make(chan int)
timeout := time.After(2 * time.Second)
select {
case result := <-ch:
fmt.Println("Received:", result)
case <-timeout:
fmt.Println("Operation timed out")
}
}
Fan-In Pattern
The fan-in pattern merges multiple input channels into a single output channel:
func fanInPattern(ch1, ch2 <-chan int) <-chan int {
merged := make(chan int)
go func() {
for {
select {
case v := <-ch1:
merged <- v
case v := <-ch2:
merged <- v
}
}
}()
return merged
}
Cancellation Pattern
Managing goroutine cancellation using select and context:
func cancelableOperation(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("Operation cancelled")
return
default:
// Perform ongoing work
}
}
}
Concurrent Patterns Comparison
Pattern |
Use Case |
Key Characteristics |
Timeout |
Preventing indefinite blocking |
Sets maximum wait time |
Fan-In |
Aggregating multiple channels |
Combines multiple inputs |
Cancellation |
Graceful goroutine termination |
Allows controlled stopping |
Select Flow for Concurrent Patterns
graph TD
A[Input Channels] --> B{Select Statement}
B --> |Timeout| C[Handle Timeout]
B --> |Fan-In| D[Merge Channels]
B --> |Cancellation| E[Stop Goroutine]
Advanced Select Techniques
- Dynamic Channel Selection
- Non-Blocking Channel Operations
- Priority-Based Channel Handling
Practical Example: Worker Pool
func workerPool(jobs <-chan int, results chan<- int) {
for {
select {
case job, ok := <-jobs:
if !ok {
return
}
results <- processJob(job)
}
}
}
- Minimize blocking time
- Use buffered channels when appropriate
- Implement proper error handling
- Avoid excessive goroutine creation
LabEx recommends practicing these patterns to develop robust concurrent applications in Go. Understanding these select patterns will significantly improve your concurrent programming skills.