Advanced Context Patterns
Context Composition and Inheritance
Context in Go allows for sophisticated composition and inheritance strategies that enable complex request management and resource coordination.
Context Composition Strategies
graph TD
A[Root Context] --> B[Parent Context]
B --> C[Child Context 1]
B --> D[Child Context 2]
C --> E[Grandchild Context]
D --> F[Grandchild Context]
Concurrent Request Handling
package main
import (
"context"
"fmt"
"sync"
"time"
)
func fetchData(ctx context.Context, id int, results chan<- string, wg *sync.WaitGroup) {
defer wg.Done()
select {
case <-time.After(time.Duration(id) * time.Second):
select {
case <-ctx.Done():
fmt.Printf("Request %d cancelled\n", id)
return
case results <- fmt.Sprintf("Data for ID %d", id):
}
case <-ctx.Done():
fmt.Printf("Request %d cancelled before completion\n", id)
}
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
results := make(chan string, 3)
var wg sync.WaitGroup
for i := 1; i <= 5; i++ {
wg.Add(1)
go fetchData(ctx, i, results, &wg)
}
go func() {
wg.Wait()
close(results)
}()
for result := range results {
fmt.Println(result)
}
}
Context Pattern Comparison
Pattern |
Characteristics |
Use Case |
Timeout Context |
Automatic cancellation after duration |
API calls, external service requests |
Value Context |
Carry request-scoped data |
Authentication, tracing |
Cancellation Context |
Manually controllable cancellation |
Complex workflow management |
Custom Context Implementation
type CustomContext struct {
context.Context
correlationID string
}
func WithCorrelationID(parent context.Context, correlationID string) *CustomContext {
return &CustomContext{
Context: parent,
correlationID: correlationID,
}
}
func (c *CustomContext) CorrelationID() string {
return c.correlationID
}
Context Propagation in Microservices
func makeServiceCall(ctx context.Context, url string) error {
// Propagate existing context to service call
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return err
}
resp, err := http.DefaultClient.Do(req)
// Handle response
return err
}
Advanced Cancellation Techniques
func orchestrateTask(ctx context.Context) error {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
errChan := make(chan error, 3)
go func() {
errChan <- performSubTask1(ctx)
}()
go func() {
errChan <- performSubTask2(ctx)
}()
select {
case err := <-errChan:
cancel() // Cancel all other tasks
return err
case <-ctx.Done():
return ctx.Err()
}
}
Best Practices for Advanced Context Usage
- Use context for cross-cutting concerns
- Implement graceful degradation
- Avoid over-complicating context usage
- Always respect context cancellation
Empowered by LabEx - Elevating Technical Expertise.