Error Utilities
The errutils
package provides enhanced error handling capabilities for Go applications. It offers utilities for working with multiple errors simultaneously and creating custom error types with consistent formatting.
Features
- Multiple Error Handling: Collect and manage multiple errors as a single entity
- Thread Safety: Concurrent-safe error collection
- Custom Error Templates: Create reusable error templates with consistent formatting
- Error Type Checking: Check for specific error types within a collection of errors
- Simple API: Easy-to-use interface for common error handling scenarios
Core Components
MultiError
The MultiError
type provides a way to collect and manage multiple errors:
type MultiError struct {
// internal fields omitted
}
Key Methods:
Add(err error)
: Adds an error to the collection (nil errors are ignored)GetAll() []error
: Returns all collected errorsError() string
: Implements the error interface, returns all errors as a newline-separated stringHasErrors() bool
: Checks if any errors are presentHasError(err error) bool
: Checks if a specific error type is present in the collection
CustomError
The CustomError
type provides a template-based approach to creating consistent error messages:
type CustomError struct {
// internal fields omitted
}
Key Methods:
Err(params ...any) error
: Creates a new error using the template and provided parameters
Usage Examples
Working with Multiple Errors
package main
import (
"fmt"
"oss.nandlabs.io/golly/errutils"
"errors"
)
func main() {
// Create a new multi-error
multiErr := errutils.NewMultiErr(nil)
// Add some errors
multiErr.Add(errors.New("first error"))
multiErr.Add(errors.New("second error"))
// Skip nil errors (they won't be added)
multiErr.Add(nil)
// Check if there are any errors
if multiErr.HasErrors() {
fmt.Println("Collected errors:")
fmt.Println(multiErr.Error())
}
// Get all errors for custom handling
allErrors := multiErr.GetAll()
fmt.Printf("Number of errors: %d\n", len(allErrors))
// Error type checking
specificErr := errors.New("specific error")
multiErr.Add(specificErr)
if multiErr.HasError(specificErr) {
fmt.Println("Found the specific error")
}
}
Using Custom Error Templates
package main
import (
"fmt"
"oss.nandlabs.io/golly/errutils"
)
func main() {
// Create reusable error templates
notFoundErr := errutils.NewCustomError("resource %s not found")
invalidParamErr := errutils.NewCustomError("invalid parameter: %s (must be %v)")
// Use the templates to create specific errors
userNotFoundErr := notFoundErr.Err("user")
fmt.Println(userNotFoundErr) // Output: resource user not found
invalidAgeErr := invalidParamErr.Err("age", "greater than 0")
fmt.Println(invalidAgeErr) // Output: invalid parameter: age (must be greater than 0)
}
Combining Multiple Errors with Custom Errors
package main
import (
"fmt"
"oss.nandlabs.io/golly/errutils"
)
func validateUser(name string, age int) *errutils.MultiError {
validationErr := errutils.NewMultiErr(nil)
// Create error templates
requiredFieldErr := errutils.NewCustomError("required field missing: %s")
invalidValueErr := errutils.NewCustomError("invalid value for %s: %v")
// Validate name
if name == "" {
validationErr.Add(requiredFieldErr.Err("name"))
}
// Validate age
if age <= 0 {
validationErr.Add(invalidValueErr.Err("age", age))
}
return validationErr
}
func main() {
// Valid user
err1 := validateUser("John", 30)
if !err1.HasErrors() {
fmt.Println("User 1 is valid")
}
// Invalid user
err2 := validateUser("", -5)
if err2.HasErrors() {
fmt.Println("User 2 validation errors:")
fmt.Println(err2.Error())
}
}
Installation
go get oss.nandlabs.io/golly/errutils