Advanced Use Cases
Sophisticated Channel Patterns
1. Fan-Out/Fan-In Design
func fanOutFanIn() {
jobs := make(chan int, 100)
results := make(chan int, 100)
// Multiple worker goroutines
for w := 1; w <= 3; w++ {
go func(id int) {
for job := range jobs {
results <- processJob(job)
}
}(w)
}
// Distribute work
for j := 1; j <= 50; j++ {
jobs <- j
}
close(jobs)
// Collect results
for a := 1; a <= 50; a++ {
<-results
}
}
Channel Coordination Strategies
graph TD
A[Input Channel] --> B[Worker Goroutines]
B --> C[Result Channel]
C --> D[Aggregation]
2. Cancellation and Context Management
func cancelableOperation(ctx context.Context) {
ch := make(chan data, 1)
go func() {
select {
case <-ctx.Done():
fmt.Println("Operation cancelled")
return
case result := <-ch:
processResult(result)
}
}()
}
Advanced Channel Patterns
Pattern |
Description |
Key Benefit |
Semaphore |
Limit concurrent operations |
Resource control |
Pipeline |
Process data in stages |
Efficient processing |
Worker Pool |
Manage concurrent tasks |
Scalability |
3. Dynamic Rate Limiting
func rateLimitedProcessor() {
requests := make(chan int, 5)
limiter := time.Tick(200 * time.Millisecond)
go func() {
for req := range requests {
<-limiter
processRequest(req)
}
}()
}
Complex Synchronization Techniques
Barrier Synchronization
func barrierSync(participants int) {
barrier := make(chan struct{})
for i := 0; i < participants; i++ {
go func(id int) {
// Prepare
barrier <- struct{}{}
// Wait for all to be ready
if len(barrier) == participants {
// Start simultaneous execution
}
}(i)
}
}
- Minimize channel contention
- Use buffered channels judiciously
- Implement proper error handling
At LabEx, we recommend carefully designing channel patterns to maximize concurrent performance and maintainability.
Error Handling in Advanced Scenarios
func robustChannelOperation() error {
ch := make(chan result, 1)
errCh := make(chan error, 1)
go func() {
defer close(ch)
defer close(errCh)
select {
case ch <- performOperation():
case errCh <- processError():
}
}()
select {
case res := <-ch:
return processResult(res)
case err := <-errCh:
return err
}
}
Key Takeaways
- Channels are powerful for complex concurrent patterns
- Design for flexibility and error resilience
- Balance between performance and readability