Home >Backend Development >Golang >How Can I Achieve Recursive Error Wrapping with Is() and As() in Go?

How Can I Achieve Recursive Error Wrapping with Is() and As() in Go?

Barbara Streisand
Barbara StreisandOriginal
2024-12-11 10:42:11302browse

How Can I Achieve Recursive Error Wrapping with Is() and As() in Go?

Go Errors: Is() and As() Support Recursive Error Wrapping

In Go, error handling is crucial for managing and analyzing errors throughout the application. The error interface provides a common way to represent errors, and it includes methods like Is() and As() for error introspection.

However, it's important to note that the standard error interface does not support recursive error wrapping. This means that if you use fmt.Errorf to wrap errors, you won't be able to use Is() and As() to check for underlying errors recursively.

Custom Error Type for Recursive Error Wrapping

To achieve recursive error wrapping, you can create a custom error type that implements the error interface. This type should include a reference to the wrapped error and define custom Is() and As() methods to enable recursive comparisons.

Here's an example implementation of a recursive error type:

type errorChain struct {
    err  error
    next *errorChain
}

func (c errorChain) Is(err error) bool {
    // Check the current error against the given error
    if c.err == err {
        return true
    }
    // Check if there is a wrapped error and recursively call Is()
    if c.next != nil {
        return c.next.Is(err)
    }
    return false
}

func (c errorChain) As(target interface{}) bool {
    // Check if the current error As() to the target interface
    if errors.As(c.err, target) {
        return true
    }
    // Check if there is a wrapped error and recursively call As()
    if c.next != nil {
        return c.next.As(target)
    }
    return false
}

Wrapping Errors Recursively

Once you have defined a custom error type, you can wrap errors recursively using a function like the following:

func Wrap(errs ...error) error {
    if len(errs) == 0 {
        return nil
    }
    // Create the first error in the chain
    out := &errorChain{err: errs[0]}
    // Iterate over the remaining errors
    for _, err := range errs[1:] {
        // Link the errors together
        out.next = &errorChain{err: err}
        out = out.next
    }
    return out
}

Usage

You can now use this custom error type to wrap errors and check for underlying errors recursively using Is() and As(). For example:

var Err1 = errors.New("error 1")
var Err2 = errors.New("error 2")
var Err3 = errors.New("error 3")

err := Wrap(Err1, Err2, Err3)

fmt.Println(errors.Is(err, Err2)) // true
fmt.Println(errors.Is(err, Err3)) // true
fmt.Println(errors.Is(err, Err0)) // false

Conclusion

By creating a custom error type with recursive Is() and As() methods, you can achieve recursive error wrapping and perform more precise error handling in your Go applications.

The above is the detailed content of How Can I Achieve Recursive Error Wrapping with Is() and As() in Go?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn