diff --git a/README.md b/README.md index ddfeaa7..4745c51 100644 --- a/README.md +++ b/README.md @@ -133,68 +133,68 @@ Supported types: `int`, `int8`, `int16`, `int32`, `int64`, `uint`, `uint8`, `uin Advanced error handling utilities. -**HandleError** - Process errors with custom matchers +**Handle** - Process errors with custom matchers ```go import "go.aykhans.me/go-utils/errors" -handled, result := errors.HandleError(err, - errors.OnSentinelError(io.EOF, func(e error) error { +handled, result := errors.Handle(err, + errors.OnSentinel(io.EOF, func(e error) error { return nil // EOF is expected, ignore it }), - errors.OnCustomError(func(e *CustomError) error { + errors.OnType(func(e *CustomError) error { return fmt.Errorf("custom error: %w", e) }), ) ``` -**HandleErrorOrDie** - Handle errors or panic if unhandled +**MustHandle** - Handle errors or panic if unhandled ```go -result := errors.HandleErrorOrDie(err, - errors.OnSentinelError(context.Canceled, func(e error) error { +result := errors.MustHandle(err, + errors.OnSentinel(context.Canceled, func(e error) error { return fmt.Errorf("operation canceled") }), ) // Panics if err doesn't match any handler ``` -**HandleErrorOrDefault** - Handle errors with a default fallback +**HandleOr** - Handle errors with a default fallback ```go -result := errors.HandleErrorOrDefault(err, +result := errors.HandleOr(err, func(e error) error { // Default handler for unmatched errors return fmt.Errorf("unexpected error: %w", e) }, - errors.OnSentinelError(context.Canceled, func(e error) error { + errors.OnSentinel(context.Canceled, func(e error) error { return fmt.Errorf("operation canceled") }), - errors.OnCustomError(func(e *ValidationError) error { + errors.OnType(func(e *ValidationError) error { return fmt.Errorf("validation failed: %w", e) }), ) // Pass nil to suppress unmatched errors -result := errors.HandleErrorOrDefault(err, nil, - errors.OnSentinelError(io.EOF, func(e error) error { +result := errors.HandleOr(err, nil, + errors.OnSentinel(io.EOF, func(e error) error { return errors.New("EOF handled") }), ) // Returns nil for unmatched errors ``` -**OnSentinelError** - Create matcher for sentinel errors (like `io.EOF`) +**OnSentinel** - Create matcher for sentinel errors (like `io.EOF`) ```go -matcher := errors.OnSentinelError(io.EOF, func(e error) error { +matcher := errors.OnSentinel(io.EOF, func(e error) error { log.Println("reached end of file") return nil }) ``` -**OnCustomError** - Create matcher for custom error types +**OnType** - Create matcher for custom error types ```go type ValidationError struct { Field string Msg string } -matcher := errors.OnCustomError(func(e *ValidationError) error { +matcher := errors.OnType(func(e *ValidationError) error { log.Printf("validation failed on field %s", e.Field) return fmt.Errorf("invalid input: %w", e) }) diff --git a/errors/handler.go b/errors/handler.go index 7b4da48..e4969c9 100644 --- a/errors/handler.go +++ b/errors/handler.go @@ -21,6 +21,9 @@ type ErrorMatcher struct { // or (false, nil) if no matcher matches the error. // If err is nil, returns (true, nil). // +// Deprecated: HandleError is deprecated and will be removed in a future release. +// Use Handle instead, which provides the same functionality. +// // Example: // // handled, result := HandleError(err, @@ -58,11 +61,31 @@ func HandleError(err error, matchers ...ErrorMatcher) (bool, error) { return false, err // No matcher found } +// Handle processes an error against a list of matchers and executes the appropriate handler. +// It returns (true, handlerResult) if a matching handler is found and executed, +// or (false, nil) if no matcher matches the error. +// If err is nil, returns (true, nil). +// +// Example: +// +// handled, result := Handle(err, +// OnSentinel(io.EOF, func(e error) error { +// return nil // EOF is expected, ignore it +// }), +// OnType(func(e *CustomError) error { +// return fmt.Errorf("custom error: %w", e) +// }), +// ) +var Handle = HandleError + // HandleErrorOrDie processes an error against a list of matchers and executes the appropriate handler. // If a matching handler is found, it returns the handler's result. // If no matcher matches the error, it panics with a descriptive message. // This function is useful when all expected error types must be handled explicitly. // +// Deprecated: HandleErrorOrDie is deprecated and will be removed in a future release. +// Use MustHandle instead, which provides the same functionality. +// // Example: // // result := HandleErrorOrDie(err, @@ -81,6 +104,23 @@ func HandleErrorOrDie(err error, matchers ...ErrorMatcher) error { return err } +// MustHandle processes an error against a list of matchers and executes the appropriate handler. +// If a matching handler is found, it returns the handler's result. +// If no matcher matches the error, it panics with a descriptive message. +// This function is useful when all expected error types must be handled explicitly. +// +// Example: +// +// result := MustHandle(err, +// OnSentinel(context.Canceled, func(e error) error { +// return fmt.Errorf("operation canceled") +// }), +// OnType(func(e *ValidationError) error { +// return fmt.Errorf("validation failed: %w", e) +// }), +// ) // Panics if err doesn't match any handler +var MustHandle = HandleErrorOrDie + // HandleErrorOrDefault processes an error against a list of matchers and executes the appropriate handler. // If a matching handler is found, it returns the handler's result. // If no matcher matches the error, it executes the default handler (dft) and returns its result. @@ -88,6 +128,9 @@ func HandleErrorOrDie(err error, matchers ...ErrorMatcher) error { // This function is useful when you want to handle specific error cases explicitly // while providing a fallback handler for all other errors. // +// Deprecated: HandleErrorOrDefault is deprecated and will be removed in a future release. +// Use HandleOr instead, which provides the same functionality. +// // Example: // // result := HandleErrorOrDefault(err, @@ -120,6 +163,36 @@ func HandleErrorOrDefault(err error, dft ErrorHandler, matchers ...ErrorMatcher) return err } +// HandleOr processes an error against a list of matchers and executes the appropriate handler. +// If a matching handler is found, it returns the handler's result. +// If no matcher matches the error, it executes the default handler (dft) and returns its result. +// If dft is nil, unmatched errors return nil (effectively suppressing the error). +// This function is useful when you want to handle specific error cases explicitly +// while providing a fallback handler for all other errors. +// +// Example: +// +// result := HandleOr(err, +// func(e error) error { +// // Default handler for unmatched errors +// return fmt.Errorf("unexpected error: %w", e) +// }, +// OnSentinel(context.Canceled, func(e error) error { +// return fmt.Errorf("operation canceled") +// }), +// OnType(func(e *ValidationError) error { +// return fmt.Errorf("validation failed: %w", e) +// }), +// ) +// +// // Suppress unmatched errors by passing nil as default handler +// result := HandleOr(err, nil, +// OnSentinel(io.EOF, func(e error) error { +// return errors.New("EOF handled") +// }), +// ) // Returns nil for unmatched errors +var HandleOr = HandleErrorOrDefault + // OnSentinelError creates an ErrorMatcher for sentinel errors. // Sentinel errors are predefined error values that are compared using errors.Is. // @@ -130,6 +203,9 @@ func HandleErrorOrDefault(err error, dft ErrorHandler, matchers ...ErrorMatcher) // The handler function receives the original error and can return a new error // or nil to suppress it. // +// Deprecated: OnSentinelError is deprecated and will be removed in a future release. +// Use OnSentinel instead, which provides the same functionality. +// // Example: // // matcher := OnSentinelError(io.EOF, func(e error) error { @@ -144,6 +220,24 @@ func OnSentinelError(sentinelErr error, handler ErrorHandler) ErrorMatcher { } } +// OnSentinel creates an ErrorMatcher for sentinel errors. +// Sentinel errors are predefined error values that are compared using errors.Is. +// +// This is used with Handle or MustHandle to match specific error +// values like io.EOF, context.Canceled, or custom sentinel errors defined with +// errors.New or fmt.Errorf. +// +// The handler function receives the original error and can return a new error +// or nil to suppress it. +// +// Example: +// +// matcher := OnSentinel(io.EOF, func(e error) error { +// log.Println("reached end of file") +// return nil // suppress EOF error +// }) +var OnSentinel = OnSentinelError + // OnCustomError creates an ErrorMatcher for custom error types. // Custom error types are struct types that implement the error interface, // and are matched using errors.As to unwrap error chains. @@ -155,6 +249,9 @@ func OnSentinelError(sentinelErr error, handler ErrorHandler) ErrorMatcher { // This is particularly useful for handling errors with additional context or data, // such as validation errors, network errors, or domain-specific errors. // +// Deprecated: OnCustomError is deprecated and will be removed in a future release. +// Use OnType instead, which provides the same functionality. +// // Example: // // type ValidationError struct { @@ -183,3 +280,32 @@ func OnCustomError[T error](handler func(T) error) ErrorMatcher { IsSentinel: false, } } + +// OnType creates an ErrorMatcher for custom error types. +// Custom error types are struct types that implement the error interface, +// and are matched using errors.As to unwrap error chains. +// +// The type parameter T specifies the error type to match. The handler function +// receives the unwrapped typed error, allowing you to access type-specific fields +// and methods. +// +// This is particularly useful for handling errors with additional context or data, +// such as validation errors, network errors, or domain-specific errors. +// +// Example: +// +// type ValidationError struct { +// Field string +// Msg string +// } +// func (e *ValidationError) Error() string { +// return fmt.Sprintf("%s: %s", e.Field, e.Msg) +// } +// +// matcher := OnType(func(e *ValidationError) error { +// log.Printf("validation failed on field %s: %s", e.Field, e.Msg) +// return fmt.Errorf("invalid input: %w", e) +// }) +func OnType[T error](handler func(T) error) ErrorMatcher { + return OnCustomError(handler) +}