Error Handling Techniques
Error Handling Strategies
Effective error handling is crucial for building robust and reliable Go applications. This section explores various techniques to manage and respond to errors.
Sentinel Errors
Predefined errors for specific conditions:
var (
ErrNotFound = errors.New("resource not found")
ErrPermissionDenied = errors.New("permission denied")
)
func findResource(id string) error {
if !resourceExists(id) {
return ErrNotFound
}
return nil
}
Error Type Checking
func handleError(err error) {
switch {
case errors.Is(err, ErrNotFound):
// Handle not found scenario
case errors.Is(err, ErrPermissionDenied):
// Handle permission issues
default:
// Generic error handling
}
}
Error Flow Management
graph TD
A[Error Occurs] --> B{Error Type}
B -->|Sentinel Error| C[Specific Handling]
B -->|Custom Error| D[Detailed Processing]
B -->|Unknown Error| E[Fallback Mechanism]
Error Handling Patterns
Pattern |
Description |
Use Case |
Sentinel Errors |
Predefined error types |
Specific condition checks |
Error Wrapping |
Add context to errors |
Detailed error tracing |
Custom Error Types |
Implement complex error logic |
Advanced error management |
Panic and Recover
func safeOperation() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
// Potentially risky operation
riskyFunction()
}
Logging and Error Reporting
func processRequest(req *Request) error {
logger := log.New(os.Stderr, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)
if err := validateRequest(req); err != nil {
logger.Printf("Request validation failed: %v", err)
return fmt.Errorf("invalid request: %w", err)
}
return nil
}
Advanced Error Handling
Custom Error Types with Additional Context
type ValidationError struct {
Field string
Value interface{}
Message string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("validation error: %s - %v (%s)",
e.Field, e.Value, e.Message)
}
Error Handling Best Practices
- Always handle errors
- Provide meaningful error messages
- Use error wrapping for context
- Avoid silent failures
- Log errors for debugging
Error Propagation
func processData(data []byte) error {
if len(data) == 0 {
return fmt.Errorf("processing failed: %w", ErrEmptyData)
}
result, err := parseData(data)
if err != nil {
return fmt.Errorf("data parsing error: %w", err)
}
return nil
}
Conclusion
Mastering error handling techniques in Go requires a combination of strategic approaches, careful error management, and consistent implementation of error-handling patterns.