Es The (t, Error) Pattern Affect Api
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 pattern shapes APIs before any implementation exists. When you design a function that can fail, Go's signature forces the question: what does the caller get back on failure? A (T, error) return says 'you might get nothing but an explanation.' The signature is the contract, and it's impossible to add a failure mode later without changing it — every caller sees and adapts. Compare adding a new thrown exception in another language: existing callers find out when it flies past them at runtime.
This pushes toward a particular style of API: fewer things that 'sometimes fail silently,' more small operations with clear failure contracts. Constructors become pairs — NewX() (X, error) — and the zero-value-vs-validation debate (make invalid states unrepresentable vs a usable zero value) plays out in every design.
It also standardizes the caller's shape. Every consumer of a fallible API has the same skeleton — call, check, wrap-or-handle — so teams can read each other's failure paths fluently. The uniformity is the point: a Go codebase reads like one style of error handling, not N personal ones.
// the signature IS the failure contract:
func Load(path string) (Config, error) // can fail — caller sees it
func NewBuffer() *bytes.Buffer // zero value usable — can't fail
// callers cannot ignore the failure without writing _:
cfg, _ := Load(path) // the _ is a visible choice, flagged by lintersEs The (t, Error) Pattern Affect Api
Direct Answer
It forces explicit failure modeling: every call site answers 'what happens if this fails?' — visible branches instead of hidden throws.
Deep Dive & Architecture
The design pressure shows best at the boundaries. Consider a config loader:
// Option A: panics on bad config — callers get crashes for input problems
// Option B: returns (Config, error) — callers decide: exit, default, retry
func Load(path string) (Config, error)
Option B is forced honesty: the API author had to decide which failures belong to the caller. That decision is API design. Option A offloads it to whoever hits the panic — the caller becomes the error handler by surprise, with less context than the library had.
The same forcing appears in constructors. A constructor that can fail must return (T, error) — so the type's zero value becomes a design question: is a zero Config usable (use a default) or invalid (require New)? Go's answer varies by type — usable zero values are idiomatic (bytes.Buffer works zero-constructed) where possible, and the (T, error) constructor exists for the cases where validation is mandatory. Neither escape hatch exists in exception-based APIs; the signature can't pose the question. That's the pattern's real gift to API design: the failure contract is a first-class, typed part of the interface, not folklore in the docs.
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?
- When would you use Multiple Return Error in a real project?
- How would you compare Multiple Return Error with an alternative?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.