</>
Skip to content
Go lessons (26/34)

Go — Error Handling

Error interface

type error interface {
    Error() string
}

Creating errors

import "errors"

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("division by zero")
    }
    return a / b, nil
}

// Formatted error
func process(age int) error {
    if age < 0 {
        return fmt.Errorf("invalid age: %d", age)
    }
    return nil
}

Custom error types

type ValidationError struct {
    Field   string
    Message string
}

func (e *ValidationError) Error() string {
    return fmt.Sprintf("%s: %s", e.Field, e.Message)
}

func validate(name string, age int) error {
    if name == "" {
        return &ValidationError{Field: "name", Message: "required"}
    }
    if age < 0 {
        return &ValidationError{Field: "age", Message: "must be positive"}
    }
    return nil
}

Error wrapping

func readConfig(path string) error {
    data, err := os.ReadFile(path)
    if err != nil {
        return fmt.Errorf("reading config: %w", err)
    }
    // process data...
    return nil
}

// Unwrap to get original error
var pathErr *os.PathError
if errors.As(err, &pathErr) {
    fmt.Println("Path:", pathErr.Path)
}

// Check specific error
if errors.Is(err, os.ErrNotExist) {
    fmt.Println("File not found")
}

Sentinel errors

var (
    ErrNotFound     = errors.New("not found")
    ErrUnauthorized = errors.New("unauthorized")
    ErrInternal     = errors.New("internal error")
)

func findUser(id string) (User, error) {
    // ...
    return User{}, ErrNotFound
}

Panic and recover

func risky() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered:", r)
        }
    }()
    panic("something went wrong")
}

func main() {
    risky() // Prints: Recovered: something went wrong
}

Best practices

  • Always check errors immediately
  • Use %w for error wrapping
  • Use errors.Is and errors.As for comparison
  • Prefer returning errors over panicking
  • Use sentinel errors for well-known conditions

Mini Practice

Write Go code that:

  1. Creates a function that returns an error
  2. Wraps an error with %w
  3. Creates a custom error type
  4. Uses recover to handle a panic

Up Next

In the next lesson, you'll learn about Goroutines — concurrent execution in Go.

Related Topics

Frequently Asked Questions about Error Handling

What is Error Handling in Go?

Error Handling is a fundamental concept in Go. This lesson explains it step by step with clear examples, making it easy for beginners to understand.

How do I learn Error Handling?

Start by reading the explanation above, then try the code examples. Practice by modifying the examples and experimenting with different values. Hands-on practice is the best way to learn Error Handling.

Why is Error Handling important in Go?

Error Handling is essential for Go development. Understanding this concept will help you write better code and solve real-world problems more effectively.