Golang errors.Unwrap Function

The errors.Unwrap function in Go is used to retrieve the next error in a chain of wrapped errors. This function is part of the errors package and is particularly useful when you need to access the underlying error that has been wrapped with additional context.

Syntax

func Unwrap(err error) error

Parameters:

  • err: The error from which to retrieve the underlying error. This error might have been wrapped with additional context using functions like fmt.Errorf.

Returns:

  • error: The next error in the chain if it exists; otherwise, it returns nil.

Example Usage

Basic Example

This example demonstrates how to use errors.Unwrap to retrieve the underlying error from a wrapped error.

package main

import (
	"errors"
	"fmt"
)

func main() {
	originalErr := errors.New("original error")
	wrappedErr := fmt.Errorf("an error occurred: %w", originalErr)

	unwrappedErr := errors.Unwrap(wrappedErr)

	fmt.Println("Wrapped Error:", wrappedErr)
	fmt.Println("Unwrapped Error:", unwrappedErr)
}

Output:

Wrapped Error: an error occurred: original error
Unwrapped Error: original error

Explanation:

  • The errors.New function creates an originalErr.
  • The fmt.Errorf function wraps the originalErr with additional context.
  • The errors.Unwrap function retrieves the originalErr from the wrapped error.

Working with Multiple Levels of Wrapping

The errors.Unwrap function can be used to step through multiple levels of wrapped errors.

Example

package main

import (
	"errors"
	"fmt"
)

func main() {
	level1Err := errors.New("level 1 error")
	level2Err := fmt.Errorf("level 2 error: %w", level1Err)
	level3Err := fmt.Errorf("level 3 error: %w", level2Err)

	fmt.Println("Level 3 Error:", level3Err)

	// Unwrap level 3 to level 2
	level2 := errors.Unwrap(level3Err)
	fmt.Println("Level 2 Error:", level2)

	// Unwrap level 2 to level 1
	level1 := errors.Unwrap(level2)
	fmt.Println("Level 1 Error:", level1)
}

Output:

Level 3 Error: level 3 error: level 2 error: level 1 error
Level 2 Error: level 2 error: level 1 error
Level 1 Error: level 1 error

Explanation:

  • The errors are wrapped at different levels, with each level adding more context to the error.
  • The errors.Unwrap function is used to step through the error chain, retrieving each underlying error.

Using errors.Unwrap in Custom Error Types

You can implement custom error types that support unwrapping by implementing the Unwrap method.

Example

package main

import (
	"errors"
	"fmt"
)

type MyError struct {
	Msg string
	Err error
}

func (e *MyError) Error() string {
	return fmt.Sprintf("%s: %v", e.Msg, e.Err)
}

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

func main() {
	originalErr := errors.New("original error")
	myErr := &MyError{Msg: "my custom error", Err: originalErr}

	unwrappedErr := errors.Unwrap(myErr)

	fmt.Println("My Error:", myErr)
	fmt.Println("Unwrapped Error:", unwrappedErr)
}

Output:

My Error: my custom error: original error
Unwrapped Error: original error

Explanation:

  • The MyError type implements the Error and Unwrap methods, allowing it to be unwrapped using errors.Unwrap.
  • The errors.Unwrap function retrieves the underlying originalErr from MyError.

Checking for a Specific Error in a Chain

The errors.Unwrap function can be used in a loop to iterate through an error chain and check for a specific error.

Example

package main

import (
	"errors"
	"fmt"
)

var ErrPermission = errors.New("permission denied")

func main() {
	originalErr := ErrPermission
	wrappedErr := fmt.Errorf("operation failed: %w", originalErr)
	moreWrappedErr := fmt.Errorf("additional context: %w", wrappedErr)

	err := moreWrappedErr

	for err != nil {
		if errors.Is(err, ErrPermission) {
			fmt.Println("Found permission denied error.")
			break
		}
		err = errors.Unwrap(err)
	}
}

Output:

Found permission denied error.

Explanation:

  • The code wraps the ErrPermission error multiple times.
  • A loop is used to unwrap the errors and check if any of them match ErrPermission.

Conclusion

The errors.Unwrap function in Go is used for working with wrapped errors, allowing you to access the underlying error that has been wrapped with additional context. This function is especially helpful in scenarios where you need to dig deeper into the error chain to understand the root cause of an error. By using errors.Unwrap, you can create more detailed and informative error-handling logic, making your Go applications more robust and easier to debug.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top