How do you idiomatically return a recoverable error and result in Go?
This tests Go's multiple-return error idiom. A strong answer gives a (T, error) signature with error last, returns nil on success, and checks err before using the result. A red flag is suggesting panic for recoverable errors or pointer out-parameters.
WHAT THIS TESTS: This question probes whether you understand Go's philosophy of explicit, local error handling through multiple return values rather than exceptions or side channels. The interviewer wants to see that you know the mechanical convention, error-last ordering, and the caller-side discipline of checking errors immediately.
A GOOD ANSWER COVERS: A good answer hits four things in order. First, state the signature pattern: func Name() (ResultType, error) with error always as the final return value. Second, explain the contract: on success return the valid result and a nil error, on failure return the zero value for the result type and a non-nil error built with errors.New or fmt.Errorf. Third, show caller discipline: always write result, err := Name() and check if err != nil before using result. Fourth, mention that this applies to recoverable errors; only unrecoverable programming bugs should trigger panic.
COMMON WRONG ANSWERS: The biggest red flag is suggesting panic for normal error conditions. Another mistake is returning the error via a pointer out-parameter like func Name(out *error) or using a single return with a sentinel value. Some candidates also forget to return the zero value when an error occurs, leading to partial results being used. Proposing try-catch style patterns or saying Go has exceptions is also a serious miss.
LIKELY FOLLOW-UPS: The interviewer may ask how you handle error wrapping and inspection, such as using fmt.Errorf with %w to preserve error chains for errors.Is or errors.As. They might also ask about naming conventions, like using err for the error variable and avoiding err1, err2. Another follow-up is how to handle cleanup when a function returns multiple values, which leads to defer patterns.
ONE CONCRETE EXAMPLE: Here is a minimal example. Define func divide(a, b float64) (float64, error). If b is zero, return 0 and errors.New("division by zero"). Otherwise return a / b and nil. The caller writes result, err := divide(4, 2) and immediately checks if err != nil before printing result. This demonstrates the zero-value plus error pattern and the mandatory caller check.
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.