Re The Conventions For The Error Return
Fast recall
Quick revision
Core answer
Practical understanding of Multiple Return Error.
Repeating a definition without saying when to use it.
Give one trade-off and say how you would test it.
Interview-ready guide
Interview answer
The conventions are stable enough that the whole ecosystem can rely on them:
The error, when present, is the last return value. Not second-of-three or configurable — last. Every Go programmer reads (bytes, err) and (n int, err error) the same way because the position never varies.
On failure, the other return values should be their zero values — nil, 0, empty. This lets callers use one guard: check err first, and if it's non-nil, don't trust anything else. A function that returns a partial result AND an error splits the convention and forces callers to read docs. Don't do it: on error, return nil for the rest.
On success, error is nil. Not 'nil sometimes with a warning' — nil means the other values are valid.
And the check order: err first, because reading other values before the check is the classic bug — a failed read may return a stale or zero count that the caller then acts on. The if err != nil guard at the top of the handling block isn't ceremony; it's the sequencing that keeps invalid data from flowing.
// error is LAST; on failure, others are zero/nil; check err FIRST
data, err := os.ReadFile(path)
if err != nil {
return nil, err // nil result + error — the convention
}
return data, nil // valid data + nil errorRe The Conventions For The Error Return
Direct Answer
error is last; on failure, other values are zero/nil; on success, error is nil. Check err before using other values.
Deep Dive & Architecture
Why do these conventions hold so strictly? Because they compose. Consider a caller three layers up:
func loadUser(id string) (*User, error) {
row, err := db.Query(id) // convention: err nil → row valid
if err != nil {
return nil, err // convention: on failure, nil result
}
return row.toUser(), nil // convention: success → nil error
}
Every function obeying the conventions makes the next one simpler: the caller's job is always check-then-use, wrap-then-return. One function breaking them — returning a usable value alongside a non-nil error — forces every caller to read its docs to know whether the value is usable. Conventions fail when they're convenient to break; these survive because breaking them taxes everyone downstream.
The zero-value-on-error rule has one deliberate exception in the standard library: io.Reader's Read returns the count of bytes actually read BEFORE the error (including io.EOF). That's documented, universal, and the one case where partial results plus error is the right contract — data is precious, so you keep what you got even as you report the failure. Note how the exception proves the design: it exists only where data loss would otherwise occur, and it's documented everywhere it applies.
Common Mistakes & Pitfalls
Repeating a definition without saying when to use it.
Check your understanding
Answer these without looking back at the article.
- What is Multiple Return Error, and when would you use it?
- How would you compare Multiple Return Error with an alternative?
- What is a common mistake when using Multiple Return Error?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.