2.4 KiB
errwrap
errwrap
is a package for Go that formalizes the pattern
of wrapping errors and checking if an error contains another error.
There is a common pattern in Go of taking a returned
error
value and then wrapping it (such as with
fmt.Errorf
) before returning it. The problem with this
pattern is that you completely lose the original error
structure.
Arguably the correct approach is that you should make a
custom structure implementing the error
interface, and have
the original error as a field on that structure, such as this example. This is
a good approach, but you have to know the entire chain of possible
rewrapping that happens, when you might just care about one.
errwrap
formalizes this pattern (it doesn’t matter what
approach you use above) by giving a single interface for wrapping
errors, checking if a specific error is wrapped, and extracting that
error.
Installation and Docs
Install using go get github.com/hashicorp/errwrap
.
Full documentation is available at http://godoc.org/github.com/hashicorp/errwrap
Usage
Basic Usage
Below is a very basic example of its usage:
// A function that always returns an error, but wraps it, like a real
// function might.
func tryOpen() error {
, err := os.Open("/i/dont/exist")
_if err != nil {
return errwrap.Wrapf("Doesn't exist: {{err}}", err)
}
return nil
}
func main() {
:= tryOpen()
err
// We can use the Contains helpers to check if an error contains
// another error. It is safe to do this with a nil error, or with
// an error that doesn't even use the errwrap package.
if errwrap.Contains(err, "does not exist") {
// Do something
}
if errwrap.ContainsType(err, new(os.PathError)) {
// Do something
}
// Or we can use the associated `Get` functions to just extract
// a specific error. This would return nil if that specific error doesn't
// exist.
:= errwrap.GetType(err, new(os.PathError))
perr }
Custom Types
If you’re already making custom types that properly wrap errors, then
you can get all the functionality of errwraps.Contains
and
such by implementing the Wrapper
interface with just one
function. Example:
type AppError {
Code ErrorCodeerror
Err }
func (e *AppError) WrappedErrors() []error {
return []error{e.Err}
}
Now this works:
:= &AppError{Err: fmt.Errorf("an error")}
err if errwrap.ContainsType(err, fmt.Errorf("")) {
// This will work!
}