Documentation
¶
Overview ¶
Package compat provides compatibility functions that accept standard Go error interface instead of requiring errx.Classified types. This package is designed for users who prefer working with the standard error interface while still benefiting from errx's classification and wrapping capabilities.
Why the Parent Package Uses errx.Classified ¶
The parent errx package uses the Classified interface for several important reasons:
Type Safety: The Classified interface ensures that only valid classification types (sentinels, displayable errors, attributed errors) can be attached to errors. This prevents accidental misuse and provides compile-time guarantees.
Sealed Interface Pattern: The Classified interface uses a marker method (IsClassified) that allows the library to maintain controlled extensibility. External packages can implement Classified, but the library can identify and validate these implementations.
API Stability: By requiring Classified types, the library can evolve its internal implementation without breaking existing code that depends on the classification behavior.
Clear Intent: Using Classified makes it explicit that you're attaching metadata (classifications, displayable messages, attributes) rather than wrapping arbitrary errors in the classification chain.
How This Package Provides Flexibility ¶
This compat package provides mirror functions that accept standard Go error interface:
- compat.Wrap(text, cause, classifications...) accepts error classifications
- compat.Classify(cause, classifications...) accepts error classifications
These functions internally convert the provided error values to errx.Classified types before calling the parent package functions. This conversion is done by wrapping each error in an errx.Classified wrapper that preserves the error's identity for errors.Is and errors.As checks.
Tradeoffs ¶
Using this package involves some tradeoffs:
**Advantages:**
- Works with any error type, including third-party errors
- More flexible for codebases that heavily use standard error interface
- Easier migration path from existing error handling code
**Disadvantages:**
- Less type safety - you can accidentally pass non-classification errors
- Slightly more overhead due to additional wrapping layer
- Less clear intent - harder to distinguish classification metadata from regular errors
Stacktrace Integration ¶
Since stacktrace functionality requires errx.Classified types, this package does NOT provide mirror functions for the stacktrace package. This is an intentional design decision. If you need stack traces, you have two options:
Use stacktrace.Here() explicitly in your compat calls: err := compat.Wrap("failed", cause, stacktrace.Here())
Use the stacktrace package functions directly: err := stacktrace.Wrap("failed", cause, classification)
Example Usage ¶
// Define classification errors (can be any error type)
var ErrNotFound = errors.New("not found")
var ErrInvalid = errors.New("invalid input")
// Use compat functions with standard errors
func fetchUser(id string) error {
err := db.Query(id)
if err != nil {
return compat.Wrap("failed to fetch user", err, ErrNotFound)
}
return nil
}
// Check classifications using standard errors.Is
if errors.Is(err, ErrNotFound) {
// Handle not found case
}
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Classify ¶
Classify attaches one or more classifications to an existing error without adding context text. This is a compatibility function that accepts standard Go error interface for classifications instead of requiring errx.Classified types.
The function internally converts the provided error classifications to errx.Classified types before calling errx.Classify. This allows you to use any error type as a classification, including third-party errors and standard library errors.
If cause is nil, Classify returns nil.
Example:
var ErrValidation = errors.New("validation error")
err := validateInput(data)
return compat.Classify(err, ErrValidation)
// Later, check with errors.Is
if errors.Is(err, ErrValidation) {
// Handle validation error
}
Example ¶
ExampleClassify demonstrates using compat.Classify with standard errors
package main
import (
"errors"
"fmt"
"github.com/go-extras/errx/compat"
)
func main() {
// Define classification error
var ErrValidation = errors.New("validation error")
// Error with a clear message that doesn't need additional context
err := errors.New("email format is invalid")
// Classify without changing the message
classified := compat.Classify(err, ErrValidation)
fmt.Println(classified.Error())
fmt.Println("Is validation error:", errors.Is(classified, ErrValidation))
}
Output: email format is invalid Is validation error: true
Example (MultipleClassifications) ¶
ExampleClassify_multipleClassifications demonstrates multiple classifications
package main
import (
"errors"
"fmt"
"github.com/go-extras/errx/compat"
)
func main() {
// Define classification errors
var (
ErrDatabase = errors.New("database error")
ErrRetryable = errors.New("retryable error")
)
dbErr := errors.New("deadlock detected")
// Attach multiple classifications
err := compat.Classify(dbErr, ErrDatabase, ErrRetryable)
fmt.Println(err.Error())
fmt.Println("Is database error:", errors.Is(err, ErrDatabase))
fmt.Println("Is retryable:", errors.Is(err, ErrRetryable))
}
Output: deadlock detected Is database error: true Is retryable: true
Example (NilCause) ¶
ExampleClassify_nilCause demonstrates nil handling for Classify
package main
import (
"errors"
"fmt"
"github.com/go-extras/errx/compat"
)
func main() {
// Define classification error
var ErrValidation = errors.New("validation error")
// Classify returns nil when cause is nil
err := compat.Classify(nil, ErrValidation)
fmt.Println("Error is nil:", err == nil)
}
Output: Error is nil: true
func ClassifyNew ¶ added in v1.2.0
ClassifyNew creates a new error with the given text and immediately classifies it with one or more classifications. This is a convenience function equivalent to calling compat.Classify(errors.New(text), classifications...).
This function accepts standard Go error interface for classifications instead of requiring errx.Classified types, making it compatible with any error type including third-party errors and standard library errors.
This function is useful when you want to create a new error and classify it in a single step, reducing verbosity compared to the two-step approach.
Example:
var ErrNotFound = errors.New("not found")
var ErrDatabase = errors.New("database error")
// Instead of:
// err := compat.Classify(errors.New("user record missing"), ErrNotFound, ErrDatabase)
// You can write:
err := compat.ClassifyNew("user record missing", ErrNotFound, ErrDatabase)
fmt.Println(err.Error()) // Output: user record missing
fmt.Println(errors.Is(err, ErrNotFound)) // Output: true
fmt.Println(errors.Is(err, ErrDatabase)) // Output: true
Example ¶
ExampleClassifyNew demonstrates creating and classifying an error in one step
package main
import (
"errors"
"fmt"
"github.com/go-extras/errx/compat"
)
func main() {
// Define classification errors
var (
ErrDatabase = errors.New("database error")
ErrRetryable = errors.New("retryable error")
)
// Create a new error and classify it in one step
err := compat.ClassifyNew("connection timeout", ErrDatabase, ErrRetryable)
fmt.Println(err.Error())
fmt.Println("Is database error:", errors.Is(err, ErrDatabase))
fmt.Println("Is retryable:", errors.Is(err, ErrRetryable))
}
Output: connection timeout Is database error: true Is retryable: true
Example (WithErrxTypes) ¶
ExampleClassifyNew_withErrxTypes demonstrates ClassifyNew with errx types
package main
import (
"errors"
"fmt"
"github.com/go-extras/errx"
"github.com/go-extras/errx/compat"
)
func main() {
// Mix standard errors with errx types
var ErrNotFound = errors.New("not found")
displayable := errx.NewDisplayable("The requested user does not exist")
attrErr := errx.Attrs("user_id", 12345, "table", "users")
err := compat.ClassifyNew("user record missing from database", ErrNotFound, displayable, attrErr)
fmt.Println("Error:", err.Error())
fmt.Println("Display text:", errx.DisplayText(err))
fmt.Println("Is not found:", errors.Is(err, ErrNotFound))
fmt.Println("Has attributes:", errx.HasAttrs(err))
}
Output: Error: user record missing from database Display text: The requested user does not exist Is not found: true Has attributes: true
func Wrap ¶
Wrap wraps an error with additional context text and optional classifications. This is a compatibility function that accepts standard Go error interface for classifications instead of requiring errx.Classified types.
The function internally converts the provided error classifications to errx.Classified types before calling errx.Wrap. This allows you to use any error type as a classification, including third-party errors and standard library errors.
If cause is nil, Wrap returns nil.
Example:
var ErrNotFound = errors.New("not found")
var ErrDatabase = errors.New("database error")
err := db.Query(id)
return compat.Wrap("failed to fetch user", err, ErrNotFound, ErrDatabase)
// Later, check with errors.Is
if errors.Is(err, ErrNotFound) {
// Handle not found case
}
Example ¶
ExampleWrap demonstrates using compat.Wrap with standard errors
package main
import (
"errors"
"fmt"
"github.com/go-extras/errx/compat"
)
func main() {
// Define classification errors
var (
ErrDatabase = errors.New("database error")
ErrRetryable = errors.New("retryable error")
)
// Simulate a database error
dbErr := errors.New("connection timeout")
// Wrap with context and classifications using standard errors
err := compat.Wrap("failed to fetch user", dbErr, ErrDatabase, ErrRetryable)
fmt.Println(err.Error())
fmt.Println("Is database error:", errors.Is(err, ErrDatabase))
fmt.Println("Is retryable:", errors.Is(err, ErrRetryable))
}
Output: failed to fetch user: connection timeout Is database error: true Is retryable: true
Example (Chaining) ¶
ExampleWrap_chaining demonstrates chaining compat calls
package main
import (
"errors"
"fmt"
"github.com/go-extras/errx/compat"
)
func main() {
// Define classification errors
var (
ErrDatabase = errors.New("database error")
ErrRetryable = errors.New("retryable error")
)
// Start with a base error
baseErr := errors.New("disk full")
// Layer 1: Classify as database error
err1 := compat.Classify(baseErr, ErrDatabase)
// Layer 2: Add context and mark as retryable
err2 := compat.Wrap("failed to write transaction log", err1, ErrRetryable)
// Layer 3: Add more context
err3 := compat.Wrap("transaction commit failed", err2)
fmt.Println(err3.Error())
fmt.Println("Is database error:", errors.Is(err3, ErrDatabase))
fmt.Println("Is retryable:", errors.Is(err3, ErrRetryable))
}
Output: transaction commit failed: failed to write transaction log: disk full Is database error: true Is retryable: true
Example (NilCause) ¶
ExampleWrap_nilCause demonstrates nil handling
package main
import (
"errors"
"fmt"
"github.com/go-extras/errx/compat"
)
func main() {
// Define classification error
var ErrNotFound = errors.New("not found")
// Wrap returns nil when cause is nil
err := compat.Wrap("context", nil, ErrNotFound)
fmt.Println("Error is nil:", err == nil)
}
Output: Error is nil: true
Example (WithAttributes) ¶
ExampleWrap_withAttributes demonstrates using attributes with compat
package main
import (
"errors"
"fmt"
"github.com/go-extras/errx"
"github.com/go-extras/errx/compat"
)
func main() {
// Define classification error
var ErrDatabase = errors.New("database error")
baseErr := errors.New("query timeout")
// Create attributed error for structured logging
attrErr := errx.Attrs(
"query", "SELECT * FROM users WHERE id = ?",
"timeout_ms", 5000,
"retry_count", 3,
)
err := compat.Wrap("database query failed", baseErr, ErrDatabase, attrErr)
// Extract attributes for logging
if errx.HasAttrs(err) {
attrs := errx.ExtractAttrs(err)
fmt.Println("Error:", err.Error())
fmt.Println("Attributes:", len(attrs))
for _, attr := range attrs {
fmt.Printf(" %s: %v\n", attr.Key, attr.Value)
}
}
}
Output: Error: database query failed: query timeout Attributes: 3 query: SELECT * FROM users WHERE id = ? timeout_ms: 5000 retry_count: 3
Example (WithErrxTypes) ¶
ExampleWrap_withErrxTypes demonstrates mixing standard errors with errx types
package main
import (
"errors"
"fmt"
"github.com/go-extras/errx"
"github.com/go-extras/errx/compat"
)
func main() {
// Define classification error
var ErrNotFound = errors.New("not found")
baseErr := errors.New("user not found in database")
// Mix standard errors with errx types
displayable := errx.NewDisplayable("The requested user does not exist")
attrErr := errx.Attrs("user_id", 12345, "table", "users")
err := compat.Wrap("lookup failed", baseErr, ErrNotFound, displayable, attrErr)
fmt.Println(err.Error())
fmt.Println("Is not found:", errors.Is(err, ErrNotFound))
fmt.Println("Has attributes:", errx.HasAttrs(err))
}
Output: lookup failed: user not found in database Is not found: true Has attributes: true
Types ¶
This section is empty.