Explain errors.As. Why must the target be a pointer, and what happens if you get it wrong?
Question 298HardGo 1.22 to 1.25
errors.As(err, target any) bool finds the first error in the tree that is assignable to the type *target points at, stores it in *target, and returns true. A node can also match through an As(any) bool method. The target must be a non-nil pointer to either a type that implements error or any interface type. Otherwise As panics. go vet's errorsas check catches most of these mistakes.
_, err := os.Open("/nope")
var pe *fs.PathError
if errors.As(err, &pe) { // note: **fs.PathError
fmt.Println(pe.Op, pe.Path) // open /nope
}
// errors.As(err, pe) // panic: target must be a non-nil pointer
// var x fs.PathError
// errors.As(err, &x) // panic: *target must be interface or implement error
// // (Error has a pointer receiver, so fs.PathError doesn't implement error)
var t interface{ Timeout() bool } // interface targets are allowed
_ = errors.As(err, &t)
Go 1.26 adds the generic errors.AsType[E error](err) (E, bool), which checks types at compile time: if pe, ok := errors.AsType[*fs.PathError](err); ok { ... }. Interviewer focus: you must know whether the error type uses a pointer or value receiver, because that decides the target type.
More on Error Handling & panics
- Q296What is the difference between
%wand%vinfmt.Errorf? - Q297How does
errors.Iswork internally, and how can a custom type change its matching? - Q299What is
errors.Join? How do multi-errors interact witherrors.Is,errors.Asanderrors.Unwrap? - Q300Compare sentinel errors, typed errors and opaque errors. When would you use each?
- Q301How do you design a good custom error type? Does it matter whether
Error()has a pointer or value receiver? - Q302The nil error interface gotcha: what does this print?