How to Use errors.As in Go for Error Type Checking
In Go, use
errors.As to check if an error or any error it wraps matches a specific type and to extract that error. It takes the original error and a pointer to a target variable, returning true if the target type is found anywhere in the error chain.Syntax
The errors.As function has this syntax:
errors.As(err error, target interface{}) bool
Here, err is the error you want to check, and target is a pointer to a variable of the error type you want to find. If err or any wrapped error matches the target type, errors.As sets the target to that error and returns true.
go
package main import ( "errors" "fmt" ) func main() { var target *MyError err := someFunc() if errors.As(err, &target) { fmt.Println("Found MyError:", target.Message) } else { fmt.Println("MyError not found") } } type MyError struct { Message string } func (e *MyError) Error() string { return e.Message } func someFunc() error { return &MyError{"something went wrong"} }
Example
This example shows how to use errors.As to detect and extract a custom error type from a wrapped error.
go
package main import ( "errors" "fmt" ) type MyError struct { Message string } func (e *MyError) Error() string { return e.Message } func someFunc() error { // Wrap MyError inside another error return fmt.Errorf("wrapper: %w", &MyError{"something went wrong"}) } func main() { var target *MyError err := someFunc() if errors.As(err, &target) { fmt.Println("Found MyError:", target.Message) } else { fmt.Println("MyError not found") } }
Output
Found MyError: something went wrong
Common Pitfalls
Common mistakes when using errors.As include:
- Passing the target variable directly instead of a pointer to it (use
&target). - Using
errors.Iswhen you need to extract the error type instead of just checking equality. - Not handling wrapped errors properly, missing the chance to detect nested errors.
Always pass a pointer to the target variable so errors.As can assign the matched error.
go
package main import ( "errors" "fmt" ) type MyError struct { Message string } func (e *MyError) Error() string { return e.Message } func someFunc() error { return &MyError{"error occurred"} } func main() { var target *MyError err := someFunc() // Wrong: passing target instead of &target if errors.As(err, target) { fmt.Println("Found MyError:", target.Message) } else { fmt.Println("MyError not found") } // Correct: if errors.As(err, &target) { fmt.Println("Found MyError correctly:", target.Message) } }
Output
MyError not found
Found MyError correctly: error occurred
Quick Reference
Remember these key points when using errors.As:
- Use it to check and extract specific error types from wrapped errors.
- Always pass a pointer to the target variable.
- Returns
trueif the error or any wrapped error matches the target type. - Useful for handling custom error types in complex error chains.
Key Takeaways
Use errors.As to find and extract specific error types from wrapped errors.
Always pass a pointer to the target variable to errors.As.
errors.As returns true if the error or any wrapped error matches the target type.
It helps handle custom error types safely in error chains.
Avoid confusing errors.As with errors.Is; use As to extract, Is to check equality.