Shows another way for working with the ex ( 💃 ) errors in Go. Taste it! ❤️
go get github.com/therenotomorrow/ex@latestUsage example:
package main
import (
"errors"
"fmt"
"os"
"github.com/therenotomorrow/ex"
)
// 1. Define sentinel errors for your application domain.
// These act as stable identifiers for known error conditions.
const (
ErrConfigValidation ex.Error = "config validation failed"
ErrFileAccess ex.Error = "file access error"
)
// 2. Create a function that simulates a real-world error chain.
func loadConfig(_ string) error {
// Simulate a low-level OS error (the root cause).
// For this example, we'll use a standard library error.
underlyingErr := os.ErrPermission
// The file access layer wraps the specific OS error with our domain error.
accessErr := ErrFileAccess.Because(underlyingErr)
// The business logic layer wraps the access error with a higher-level reason.
businessErr := ErrConfigValidation.Reason("user section is missing")
// Chain multiple errors: set accessErr as the cause of businessErr
return ex.Conv(businessErr).Because(accessErr)
}
func main() {
// 3. Call the function and get the rich, chained error.
err := loadConfig("/etc/app/config.yaml")
// 4. Print the full error chain for detailed logging. 🪵
// The output is a clear, human-readable trace of what happened.
fmt.Printf("Full error: %s\n\n", err)
// 5. Check for specific errors to make programmatic decisions.
// This works even though the errors are deeply nested in the chain.
fmt.Println("Checking error identities...")
if errors.Is(err, ErrConfigValidation) {
fmt.Println("✅ High-level operation failed: Could not validate config.")
}
if errors.Is(err, ErrFileAccess) {
fmt.Println("✅ Intermediate cause: Could not access the file.")
}
// You can even check against standard library errors wrapped in the chain!
if errors.Is(err, os.ErrPermission) {
fmt.Println("✅ Root cause: Permission was denied by the OS.")
}
}
// Output:
// Full error: config validation failed: file access error: permission denied
//
// Checking error identities...
// ✅ High-level operation failed: Could not validate config.
// ✅ Intermediate cause: Could not access the file.
// ✅ Root cause: Permission was denied by the OS.go version
# go version go1.25.3
just --version
# just 1.42.4PROJECT_ROOT=ex
git clone https://github.com/therenotomorrow/ex.git "$PROJECT_ROOT"
cd "$PROJECT_ROOT"# install dependencies
go mod tidy
# check code integrity
just code test
# setup safe development (optional)
git config --local core.hooksPath .githooks# run quick checks
just test smoke # or just test
# run with coverage
just test coverPlease feel free to submit issues, fork the repository and send pull requests!
This project is licensed under the terms of the MIT license.