Error Handling

⭐ Interview Importance: HIGH
⏱️ Revision Time: 3 min

TL;DR

Go does not have try/catch blocks. Instead, errors are just normal values returned by functions. It is the caller’s explicit responsibility to check if the returned error is nil. If it’s not nil, something went wrong.

Mental Model

How It Works

An error in Go is simply a built-in interface with a single method:

type error interface {
    Error() string
}

Any struct that implements the Error() method is considered a valid error.
Because errors are returned as values (usually as the last value in a multiple-return signature), the program’s control flow remains completely linear and predictable, unlike exceptions which wildly jump across the call stack.

Example

package main

import (
	"errors"
	"fmt"
)

// A function returning a result AND an error
func divide(a, b int) (int, error) {
	if b == 0 {
		// Creating a simple string-based error
		return 0, errors.New("cannot divide by zero")
	}
	return a / b, nil
}

func main() {
    // 1. Standard Error Checking
	result, err := divide(10, 2)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("Result:", result) // 5

    // 2. Inline Error Checking (Very common in Go!)
    // The variables 'res' and 'err2' only exist inside the if-block scope.
	if res, err2 := divide(10, 0); err2 != nil {
		fmt.Println("Failed:", err2)
	} else {
		fmt.Println("Success:", res)
	}
}

Common Interview Questions

Why does Go use this verbose if err != nil pattern instead of try/catch?

The creators of Go believe that error handling is not an “exception” to the flow of a program; it is the normal, expected flow. By forcing developers to handle errors explicitly via if err != nil exactly where they happen, it results in much more robust, reliable code without hidden crashing edge-cases.

How do I create a custom Error type?

Since error is just an interface, you just create a struct and add the Error() string method to it:

type HTTPError struct {
    Code int
    Msg  string
}
func (e *HTTPError) Error() string {
    return fmt.Sprintf("HTTP %d: %s", e.Code, e.Msg)
}