Since Go 1.13, we have new helpful ways to find out the type of error, even if we use error wrapping. If we want to check if a given error matches another specific error, we need to use Is()
function from the errors
package. If we are interested in whether the error is of a given type, we should call the As()
function.
Is()
function
In the example below, we can see that the function validateInput
returns an error for badInput
. This error is ErrBadInput
wrapped in an error created by fmt.Errorf()
. Using the Is(err, target error) bool
function, we can detect the ErrBadInput
even if it is wrapped since this function checks if any error in the chain of wrapped errors matches the target. Therefore, this form should be preferable to comparison if err == ErrBadInput
.
package main
import (
"errors"
"fmt"
)
const badInput = "abc"
var ErrBadInput = errors.New("bad input")
func validateInput(input string) error {
if input == badInput {
return fmt.Errorf("validateInput: %w", ErrBadInput)
}
return nil
}
func main() {
input := badInput
err := validateInput(input)
if errors.Is(err, ErrBadInput) {
fmt.Println("bad input error")
}
}
Output:
bad input error
As()
function
Similar to Is()
, the As(err error, target interface{}) bool
checks if any error in the chain of wrapped errors matches the target. The difference is that this function checks whether the error has a specific type, unlike the Is()
, which examines if it is a particular error object. Because As
considers the whole chain of errors, it should be preferable to the type assertion if e, ok := err.(*BadInputError); ok
.
target
argument of theAs(err error, target interface{}) bool
function should be a pointer to the error type, which in this case is*BadInputError
package main
import (
"errors"
"fmt"
)
const badInput = "abc"
type BadInputError struct {
input string
}
func (e *BadInputError) Error() string {
return fmt.Sprintf("bad input: %s", e.input)
}
func validateInput(input string) error {
if input == badInput {
return fmt.Errorf("validateInput: %w", &BadInputError{input: input})
}
return nil
}
func main() {
input := badInput
err := validateInput(input)
var badInputErr *BadInputError
if errors.As(err, &badInputErr) {
fmt.Printf("bad input error occured: %s\n", badInputErr)
}
}
Output:
bad input error occured: bad input: abc