Integration, Migration & FAQ
August 29, 2025 · View on GitHub
Interfaces
go-errors provides interfaces for advanced error handling:
- ErrorCoder: Extracts the error code
- Retryable: Indicates if an error is retryable
- UserMessager: Extracts a user-friendly message
Example
var coder errors.ErrorCoder = err
code := coder.ErrorCode()
var retry errors.Retryable = err
if retry.IsRetryable() { /* ... */ }
var um errors.UserMessager = err
msg := um.UserMessage()
Testing & Coverage
Run all tests:
go test -v ./...
Check coverage:
go test -cover ./...
- Write tests for all custom error codes and logic in your application.
- Use table-driven tests for error scenarios.
- Aim for high coverage to ensure reliability.
Integration in Real Projects
- Use go-errors for all error creation and propagation in your services.
- Wrap errors at API/service boundaries to add context and user messages.
- Serialize errors to JSON for API responses.
- Use error codes for programmatic error handling in clients.
Example: REST API Handler
func handler(w http.ResponseWriter, r *http.Request) {
err := doSomething()
if err != nil {
apiErr, _ := err.(*errors.Error)
http.Error(w, apiErr.UserMessage(), 400)
// Optionally log apiErr.Stack.String() for debugging
}
}
Migration Guide: From Standard Errors to go-errors
This guide helps you migrate your Go project from standard error handling to go-errors, step by step.
1. Install go-errors
go get github.com/agilira/go-errors
2. Update Imports
Replace:
import "errors"
with:
import "github.com/agilira/go-errors"
3. Define Error Codes
Instead of using only error messages, define string constants for error codes:
const ErrCodeValidation = "VALIDATION_ERROR"
4. Replace errors.New and fmt.Errorf
Before:
return errors.New("validation failed")
After:
return errors.New(ErrCodeValidation, "Validation failed")
5. Wrapping Errors
Before:
return fmt.Errorf("db error: %w", err)
After:
return errors.Wrap(err, "DB_ERROR", "db error")
6. Add User Messages and Context
err := errors.New(ErrCodeValidation, "Validation failed").
WithUserMessage("Please check your input").
WithContext("field", "email").
WithSeverity("warning")
7. Use Helpers for Inspection
Replace manual error checks with helpers:
if errors.HasCode(err, ErrCodeValidation) { /* ... */ }
root := errors.RootCause(err)
8. Update API/Handler Logic
Return user-friendly messages in APIs:
apiErr, _ := err.(*errors.Error)
http.Error(w, apiErr.UserMessage(), 400)
9. Testing
Update your tests to check error codes and user messages, not just error strings.
Example: Before and After
Before:
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return errors.New("not found")
}
return fmt.Errorf("db error: %w", err)
}
After:
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return errors.New("NOT_FOUND", "not found").WithUserMessage("Resource not found")
}
return errors.Wrap(err, "DB_ERROR", "db error")
}
Tips
- Migrate incrementally: start from leaf packages and move up.
- Use go-errors everywhere for consistency.
- Use error codes for programmatic handling, user messages for UI/API.
FAQ
Q: Can I define my own error codes? A: Yes, define them as string constants in your application.
Q: Is go-errors compatible with the standard errors package? A: Yes, it supports errors.Is, errors.As, and errors.Unwrap.
Q: How do I attach extra context to an error? A: Use the WithContext method.
Q: How do I return user-friendly messages in APIs? A: Use WithUserMessage and UserMessage().
Q: Is stacktrace capture expensive? A: No, it is lightweight and only captured when wrapping errors.
go-errors • an AGILira library