tezvyn:

Difference between errors.Is and errors.As in Go

AI-drafted, machine-checkedSource: go.devintermediate

This tests error-chain inspection in Go. errors.Is checks sentinel equality through wrapping, such as os.ErrNotExist. errors.As extracts a custom type, like os.PathError, into a variable. A red flag is using direct == or type assertions on wrapped errors.

WHAT THIS TESTS: The interviewer wants to know if you understand Go 1.13 error wrapping mechanics and the idiomatic way to inspect error chains. Before Go 1.13, developers used direct sentinel comparison with == and type assertions, but these fail when an error is wrapped with fmt.Errorf using the %w verb or a custom Unwrap method. The question probes whether you know the standard library API that traverses the chain automatically.

A GOOD ANSWER COVERS: First, state that errors.Is checks for sentinel equality down the unwrap chain. It returns true if the error or any error it wraps matches the target sentinel exactly. Use it when you want to know if a specific known error occurred, such as checking os.ErrNotExist or a package level var ErrNotFound. Second, state that errors.As checks for type matching down the unwrap chain. It returns true if the error or any wrapped error has the same type as the target, and it copies that error into the target pointer so you can access its fields. Use it when you need to extract a custom error type, such as an os.PathError to read the Path or Op fields. Third, mention that both functions respect the Unwrap method convention introduced in Go 1.13, so they work with errors created via fmt.Errorf with %w and with custom wrapper types.

COMMON WRONG ANSWERS: A major red flag is saying you would use err == os.ErrNotExist or a type assertion to a concrete error type on an error that might be wrapped. These only inspect the top level error and silently fail when wrapping is present. Another red flag is confusing the two functions, such as claiming errors.Is extracts a type or that errors.As compares sentinels. Also avoid saying you always unwrap manually in a loop; the standard library provides these helpers precisely to avoid that boilerplate.

LIKELY FOLLOW-UPS: The interviewer may ask how wrapping works under the hood, prompting you to describe the Unwrap method convention. They might ask when to define custom error types versus sentinels, or how fmt.Errorf with %w interacts with these functions. A senior candidate might be asked about error handling strategy across API boundaries, or how to maintain backward compatibility when adding wrapping to existing code that already uses direct comparisons.

ONE CONCRETE EXAMPLE: Imagine a file open call returns an error wrapped by your storage layer: fmt.Errorf("loading config: %w", err). Downstream, use errors.Is(err, os.ErrNotExist) to detect a missing file through the wrapper. If your storage layer instead returns a custom StorageError with an Unwrap method, declare a variable se of type pointer to StorageError and call errors.As(err, &se), then retryWithBackup(se.Key) to extract the structured field and act on it.

Read the original → go.dev

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.