tezvyn:

Go's `error` Interface: Errors Are Values

AI-drafted, machine-checkedSource: go.devbeginner

In Go, an error is any value that can describe its own failure string. Functions like `os.Open` return an `error` to signal problems. The footgun is only checking for `nil` and ignoring the rich, structured data a custom error type can provide.

WHY IT EXISTS Go needed a way to handle failure conditions without resorting to exceptions or complex return codes. The solution was to treat errors as first-class values, making failure an explicit, normal part of a function's contract rather than a special case that interrupts control flow.

THE MENTAL MODEL An error in Go is not a special language feature; it's a pre-declared interface type. Any data structure that implements the Error() string method fulfills this interface. This means an error can be a simple string or a complex struct containing detailed context about what went wrong, turning errors from simple messages into inspectable values.

HOW IT WORKS The error interface is defined as type error interface { Error() string }. A function that might fail typically has error as its last return type. The caller is expected to check if the returned error is nil. If it's not nil, a failure occurred. For simple cases, errors.New("message") or fmt.Errorf("formatted %s", "message") create basic error values. For richer context, you define your own struct, add fields for details like an error code or invalid input, and implement the Error() method. The caller can then use a type assertion to check if the returned error is of your custom type and access that extra information.

WHEN TO USE IT Use the (value, error) return pattern for any function that can fail in a way the caller should handle. This is the standard for I/O operations (reading files, network requests), data parsing (JSON, XML), or any business logic where invalid input or state can occur, such as calculating the square root of a negative number.

WHEN NOT TO USE IT Do not use errors for normal control flow. For truly unrecoverable, programmer-level mistakes that should never happen (like an index out of bounds in a slice you control), Go uses a panic. A panic stops the program's ordinary execution. Errors are for expected, handleable failures; panics are for unexpected, catastrophic bugs.

ONE CANONICAL EXAMPLE A function to calculate a square root cannot operate on negative numbers. A basic version returns errors.New("math: square root of negative number"). A better version defines a custom error type like type NegativeSqrtError float64 which holds the invalid input. The caller first checks if err != nil. Then, it can use a type assertion like if e, ok := err.(NegativeSqrtError); ok to see if the error is the specific type it knows how to handle, perhaps by retrieving the original number float64(e) that caused the failure.

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.