Concurrent Control Patterns
Timeout Handling
Timeouts are crucial for preventing goroutines from hanging indefinitely. select
provides an elegant solution:
func timeoutExample() {
ch := make(chan string)
go func() {
time.Sleep(2 * time.Second)
ch <- "Delayed Message"
}()
select {
case msg := <-ch:
fmt.Println(msg)
case <-time.After(1 * time.Second):
fmt.Println("Operation timed out")
}
}
Cancellation and Context Management
func cancelableOperation(ctx context.Context) {
select {
case <-ctx.Done():
fmt.Println("Operation cancelled")
return
default:
// Perform long-running task
}
}
Multiple Channel Coordination
graph TD
A[Multiple Channels] --> B{Select Statement}
B --> C[Process First Ready Channel]
B --> D[Process Second Ready Channel]
B --> E[Handle Default Scenario]
Fan-In Pattern
Combining multiple input channels into a single output channel:
func fanInPattern(ch1, ch2 <-chan int) <-chan int {
combinedCh := make(chan int)
go func() {
for {
select {
case v := <-ch1:
combinedCh <- v
case v := <-ch2:
combinedCh <- v
}
}
}()
return combinedCh
}
Rate Limiting
Pattern |
Description |
Use Case |
Token Bucket |
Controlled resource access |
API rate limiting |
Ticker |
Periodic operations |
Scheduled tasks |
func rateLimitExample() {
requests := make(chan int, 5)
limiter := time.Tick(200 * time.Millisecond)
for req := range requests {
<-limiter
fmt.Println("Request processed:", req)
}
}
Non-Blocking Channel Operations
func nonBlockingSelect() {
ch := make(chan string, 1)
select {
case ch <- "Message":
fmt.Println("Sent message")
default:
fmt.Println("Channel is full")
}
}
Advanced Synchronization Techniques
Worker Pool Pattern
func workerPool(jobs <-chan int, results chan<- int) {
for job := range jobs {
select {
case results <- processJob(job):
// Job processed
case <-time.After(3 * time.Second):
fmt.Println("Job timed out")
}
}
}
Best Practices
- Use buffered channels for non-blocking scenarios
- Implement proper timeout mechanisms
- Avoid complex select statements
- Close channels when no longer needed
LabEx recommends careful design of select statements to prevent potential bottlenecks in concurrent applications. Always profile and test your concurrent code thoroughly.