Error Handling Practices
Comprehensive Error Handling Strategies
1. Error Handling Workflow
graph TD
A[Network Operation] --> B{Error Occurred?}
B -->|Yes| C[Classify Error]
C --> D{Recoverable?}
D -->|Yes| E[Implement Recovery]
D -->|No| F[Log and Terminate]
B -->|No| G[Continue Execution]
2. Error Handling Patterns
Pattern |
Description |
Use Case |
Retry Mechanism |
Automatically retry failed operations |
Transient network issues |
Graceful Degradation |
Provide alternative functionality |
Partial service availability |
Circuit Breaker |
Prevent repeated failed attempts |
Protect system from overload |
Practical Error Handling Implementation
Robust Connection Handling
func connectWithRetry(address string, maxRetries int) error {
for attempt := 0; attempt < maxRetries; attempt++ {
conn, err := net.DialTimeout("tcp", address, 5*time.Second)
if err == nil {
defer conn.Close()
return nil
}
// Log specific error details
log.Printf("Connection attempt %d failed: %v", attempt+1, err)
// Implement exponential backoff
backoffTime := time.Duration(math.Pow(2, float64(attempt))) * time.Second
time.Sleep(backoffTime)
}
return fmt.Errorf("failed to connect after %d attempts", maxRetries)
}
Advanced Error Handling Techniques
1. Custom Error Types
type NetworkError struct {
Op string
Err error
}
func (e *NetworkError) Error() string {
return fmt.Sprintf("network error during %s: %v", e.Op, e.Err)
}
2. Context-Aware Error Handling
func performNetworkOperation(ctx context.Context) error {
select {
case <-ctx.Done():
return fmt.Errorf("operation cancelled: %v", ctx.Err())
default:
// Perform network operation
conn, err := net.Dial("tcp", "example.com:80")
if err != nil {
return &NetworkError{
Op: "connection",
Err: err,
}
}
defer conn.Close()
return nil
}
}
Error Logging and Monitoring
Structured Logging
func logNetworkError(err error) {
switch e := err.(type) {
case *net.OpError:
log.Printf("Operation error: %v, Temporary: %v, Timeout: %v",
e, e.Temporary(), e.Timeout())
case *net.DNSError:
log.Printf("DNS resolution error: %v, IsTimeout: %v", e, e.IsTimeout)
default:
log.Printf("Unexpected error: %v", err)
}
}
Best Practices
- Always handle errors explicitly
- Provide meaningful error messages
- Implement appropriate retry mechanisms
- Use structured logging
- Consider circuit breaker patterns
LabEx recommends developing a comprehensive error handling strategy to build resilient network applications.