Comprehensive guide to Go error handling patterns including custom error types, wrapping, sentinel errors, and best practices for building robust Go applications
A comprehensive skill for understanding and implementing Go error handling patterns based on official Go documentation.
This skill teaches you to implement proper error handling in Go, covering the built-in `error` interface, custom error types, error wrapping, simplifying repetitive error handling, and building robust error infrastructure for web applications.
When a user asks about Go error handling, follow these steps:
1. **Assess the User's Need**
- Determine if they need basic error handling, custom error types, error wrapping, or architectural patterns
- Check if they have existing code that needs refactoring or are starting fresh
2. **Basic Error Handling**
- Explain the `error` interface: `type error interface { Error() string }`
- Show the standard pattern:
```go
f, err := os.Open("filename.ext")
if err != nil {
log.Fatal(err)
}
```
- Use `errors.New()` for simple string errors
- Use `fmt.Errorf()` for formatted error messages with context
3. **Custom Error Types**
- When errors need additional context, define custom types:
```go
type NegativeSqrtError float64
func (f NegativeSqrtError) Error() string {
return fmt.Sprintf("math: square root of negative number %g", float64(f))
}
```
- Show how callers can use type assertions to inspect error details:
```go
if nerr, ok := err.(net.Error); ok && nerr.Temporary() {
// handle temporary error
}
```
4. **Error Context and Wrapping**
- Always provide context in error messages (e.g., "open /etc/passwd: permission denied" not just "permission denied")
- Use `fmt.Errorf()` with format verbs to add context
- For structured errors, create custom types with additional fields (like `json.SyntaxError` with `Offset`)
5. **Simplifying Repetitive Error Handling**
- For web applications with repeated error handling, create wrapper types:
```go
type appHandler func(http.ResponseWriter, *http.Request) error
func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if err := fn(w, r); err != nil {
http.Error(w, err.Error(), 500)
}
}
```
- For richer error handling, use custom error structs:
```go
type appError struct {
Error error
Message string
Code int
}
```
6. **Best Practices to Emphasize**
- Check errors explicitly where they occur (don't ignore them)
- Provide meaningful context in error messages
- Return `error` interface, not concrete types (unless building error infrastructure)
- Use type assertions to inspect specific error types when needed
- Consider logging vs. displaying errors (debug info vs. user-facing messages)
- For panics, use `defer`, `panic`, and `recover` appropriately
7. **Code Generation and Refactoring**
- When writing new code, generate error handling that follows these patterns
- When refactoring existing code:
- Look for missing error checks
- Add context to generic error messages
- Extract repetitive error handling into helper functions or middleware
- Replace panic/recover with proper error returns where appropriate
8. **Advanced Patterns**
- Suggest error wrapping with stack traces for debugging
- Recommend structured logging for errors in production
- Show how to build error middleware for web frameworks
- Explain when to use panic (truly unrecoverable errors) vs. error returns
**User:** "Help me add proper error handling to my Go HTTP handler"
**Assistant Response:**
1. Read the existing handler code
2. Identify all error-producing operations (database calls, template rendering, etc.)
3. Implement an `appHandler` wrapper type with custom `appError` struct
4. Refactor handlers to return `*appError` with appropriate HTTP status codes and messages
5. Add structured logging for debugging while showing user-friendly messages
6. Update route registration to use the new handler type
**User:** "How do I create a custom error type for my validation logic?"
**Assistant Response:**
1. Define a struct that implements the `error` interface
2. Add fields for validation-specific context (field name, invalid value, constraint)
3. Implement the `Error() string` method with formatted message
4. Show caller code using type assertion to extract validation details
5. Demonstrate using the error in both logging and API response scenarios
Based on official Go documentation: https://go.dev/blog/error-handling-and-go
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/go-error-handling-guide/raw