Documentation
¶
Overview ¶
Package errors implements a stdlib-compatible way of wrapping more than one error into an error chain, while supporting `errors.Is` and `errors.As` (and obviously `Error()` and `Unwrap()`), thus being a drop in replacement for other error types. Errors also provides a `New()` function which works like the stdlib version.
The Standard Library allows you to wrap exactly ONE error with eg `fmt.Errorf`, and will bail out if there are more than one `%w` receiver.
`errors.Wrap` will solve that by allowing arbitrary errors to be wrapped without losing information.
A construed (well, kinda) could be a situation where a bunch of different functions are called, and if failing, returns a common error that is handled further up the stack:
```golang
if err := someFunc(); err != nil {
// MyError is handled up the stack
return MyError
}
```
This discards information about the actual error, though. Now, normally, you'd do something like:
```golang
return fmt.Errorf("%s: %w", err, MyError)
```
And while this wraps `MyError`, it doesn't wrap the actual error from `someFunc, which we might be interested in as well, maybe because some specific error requires specific handling:
So, if the error above was e.g. `mysql.ErrNotFound`, `errors.Is(err, mysql.ErrNotFound)` would be false, even if `errors.Is(err, MyError)` is true.
Instead, using `errors.Wrap`:
```golang
if err := someFunc(); err != nil {
// MyError is handled explicitly up the stack
return errors.Wrap(err, MyError)
}
```
This will make `errors.Is` return true for both, as they are now both properly wrapped.
`Unwrap` and `Wrap` both run in O(n) time, where n is the number of errors added to the chain.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var Separator = ": "
Separator between errors in the chain when they're output together with `.Error()`. Can be overridden globally by setting this value, default is ": ".
Functions ¶
func As ¶
As is a wrapper around the stdlib function, so you don't need to import both packages
Example ¶
package main
import (
"fmt"
"io/fs"
"os"
"github.com/adamhassel/errors"
)
func main() {
if _, err := os.Open("non-existing"); err != nil {
var pathError *fs.PathError
if errors.As(err, &pathError) {
fmt.Println("Failed at path:", pathError.Path)
} else {
fmt.Println(err)
}
}
}
Output: Failed at path: non-existing
func Is ¶
Is is a wrapper around the stdlib function, so you don't need to import both packages
Example ¶
package main
import (
"fmt"
"io/fs"
"os"
"github.com/adamhassel/errors"
)
func main() {
if _, err := os.Open("non-existing"); err != nil {
if errors.Is(err, fs.ErrNotExist) {
fmt.Println("file does not exist")
} else {
fmt.Println(err)
}
}
}
Output: file does not exist
func New ¶
New is a wrapper around the stdlib errors.New function, so you don't need to import both
Example ¶
package main
import (
"fmt"
"github.com/adamhassel/errors"
)
func main() {
err := errors.New("emit macho dwarf: elf header corrupted")
if err != nil {
fmt.Print(err)
}
}
Output: emit macho dwarf: elf header corrupted
Example (Errorf) ¶
The fmt package's Errorf function lets us use the package's formatting features to create descriptive error messages.
package main
import (
"fmt"
)
func main() {
const name, id = "bimmler", 17
err := fmt.Errorf("user %q (id %d) not found", name, id)
if err != nil {
fmt.Print(err)
}
}
Output: user "bimmler" (id 17) not found
func Unwrap ¶
Unwrap is a wrapper around the stdlib function, so you don't need to import both packages
func Wrap ¶
Wrap will wrap one or more errors into a single error chain, compatible with errors.As, errors.Is. Note that if you're using this as a sort of `append` analogue (`err = Wrap(err, ErrAnother)` or similar, where the result overwrites the argument), then you should protect accordingly with appropriate synchronization measures (e.g. a mutex), just as you would with `append`.
Types ¶
This section is empty.