Back to Blog

Error Handling: errors.New, Wrapping & Custom Types | Go Tutorial #19

Sandy LaneSandy Lane

Video: Error Handling: errors.New, Wrapping & Custom Types | Go Tutorial #19 by Taught by Celeste AI - AI Coding Coach

Watch full page →

Error Handling in Go: Creating, Wrapping & Custom Error Types

Go handles errors explicitly by returning error values rather than using exceptions, making error management straightforward and clear. This guide demonstrates how to create basic errors, wrap them for context, check errors effectively, and define custom error types for richer error handling.

Code

package main

import (
  "errors"
  "fmt"
)

// Sentinel error for a specific condition
var ErrNotFound = errors.New("resource not found")

// CustomError defines a custom error type with extra context
type CustomError struct {
  Code    int
  Message string
}

func (e *CustomError) Error() string {
  return fmt.Sprintf("Code %d: %s", e.Code, e.Message)
}

// fetchResource simulates a function that may return different errors
func fetchResource(id int) error {
  if id == 0 {
    // Return a basic sentinel error
    return ErrNotFound
  }
  if id < 0 {
    // Return a wrapped error with additional context
    return fmt.Errorf("invalid id %d: %w", id, ErrNotFound)
  }
  if id == 999 {
    // Return a custom error type
    return &CustomError{Code: 999, Message: "special error occurred"}
  }
  return nil // no error
}

func main() {
  ids := []int{0, -1, 999, 42}

  for _, id := range ids {
    err := fetchResource(id)
    if err != nil {
      // Check for sentinel error using errors.Is
      if errors.Is(err, ErrNotFound) {
        fmt.Println("Not found error:", err)
      } else {
        var custErr *CustomError
        // Check for custom error type using errors.As
        if errors.As(err, &custErr) {
          fmt.Println("Custom error:", custErr)
        } else {
          fmt.Println("Other error:", err)
        }
      }
    } else {
      fmt.Println("Resource", id, "fetched successfully")
    }
  }
}

Key Points

  • Use errors.New to create simple sentinel errors for common conditions.
  • Return errors explicitly from functions to indicate failure.
  • Wrap errors with fmt.Errorf and %w to add context while preserving the original error.
  • Use errors.Is to check if an error matches a sentinel error, even when wrapped.
  • Define custom error types and use errors.As to detect and extract them for specialized handling.