Rez Moss

Rez Moss

Personal Musings: A Blog for the Tech-Savvy and Curious Mind

Effective Error Creation in Go

Mar 2022

Error handling is a crucial aspect of writing robust Go code. Creating informative and useful errors is key to effective error handling. This article explores various methods of error creation in Go.

Basic Error Creation

The simplest way to create an error is using errors.New():

import "errors"

err := errors.New("something went wrong")

Formatted Errors

For more detailed errors, use fmt.Errorf():

import "fmt"

name := "file.txt"
err := fmt.Errorf("failed to open file: %s", name)

Custom Error Types

For more complex scenarios, create custom error types:

type ValidationError struct {
    Field string
    Message string
}

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

err := &ValidationError{Field: "email", Message: "invalid format"}

Error Wrapping (Go 1.13+)

Wrap errors to add context while preserving the original error:

originalErr := errors.New("database connection failed")
wrappedErr := fmt.Errorf("query failed: %w", originalErr)

// Later, you can unwrap:
fmt.Println(errors.Unwrap(wrappedErr))

Sentinel Errors

For specific error conditions that callers might want to check for:

var ErrNotFound = errors.New("item not found")

func FindItem(id string) (*Item, error) {
    // ...
    return nil, ErrNotFound
}

// Usage:
if err == ErrNotFound {
    // Handle not found case
}

Error Handling Example

func processFile(name string) error {
    f, err := os.Open(name)
    if err != nil {
        return fmt.Errorf("failed to open %s: %w", name, err)
    }
    defer f.Close()

    // Process file...
    return nil
}

Effective error creation in Go involves choosing the right method based on the complexity of the error and the information you need to convey. By following these practices, you can create clear, informative, and useful errors in your Go programs.