How to wrap and unwrap errors to access underlying error information in Go?

In Go, you can wrap and unwrap errors using the errors package or by implementing the Unwrap interface. This allows you to add additional context and information to an error while retaining the ability to access the underlying error.

Here's an example of how to wrap and unwrap errors:

Step 1: Define custom error type with a wrapped error field:

type MyError struct { message string err error }

Step 2: Implement the error interface for your custom error type:

func (e *MyError) Error() string { return e.message }

Step 3: Implement the Unwrap method to access the underlying error:

func (e *MyError) Unwrap() error { return e.err }

Step 4: Wrap an existing error with additional context:

func doSomething() error { err := someFunction() if err != nil { return &MyError{ message: "Error occurred while doing something", err: err, } } // ... return nil }

Step 5: Unwrap the error to access the underlying error information:

err := doSomething() if err != nil { if underlyingErr := errors.Unwrap(err); underlyingErr != nil { fmt.Println("Underlying error:", underlyingErr) } fmt.Println("Error:", err) }

Alternatively, you can also use the errors package to wrap and unwrap errors:

err := fmt.Errorf("outer error: %w", innerErr)

To unwrap the error, you can use the errors.Is function:

var innerErr SomeError if errors.Is(err, &innerErr) { // Handle inner error }

Note that the errors.Is function does not unwrap multiple layers of errors automatically. If you have multiple wrapped errors, you can use the errors.As function to traverse the error chain:

var innerErr SomeError if errors.As(err, &innerErr) { // Handle inner error }