← Back to Go Course | Chapter 9: Error Handling | Lesson 1 of 6

The error Interface

An error in Go is just a small box that can hold a message explaining what went wrong -- and every function that might fail hands one back for you to check.

The error Interface Itself

Go's built-in error type is just an interface with a single method, Error() string. Any type that implements this method can be used as an error, which keeps error handling simple and uniform across the whole language.

Example: The error Interface Itself

markup
package main

import "fmt"

type MyError struct {
	Msg string
}

func (e *MyError) Error() string {
	return e.Msg
}

func main() {
	var err error = &MyError{Msg: "something went wrong"}
	fmt.Println(err)
}

Creating Errors with errors.New

The simplest way to produce an error is errors.New("message"), which returns a basic error value holding that static text -- ideal for straightforward failure conditions.

Example: Creating Errors with errors.New

markup
package main

import (
	"errors"
	"fmt"
)

func checkAge(age int) error {
	if age < 0 {
		return errors.New("age cannot be negative")
	}
	return nil
}

func main() {
	if err := checkAge(-5); err != nil {
		fmt.Println("error:", err)
	}
}

Creating Errors with fmt.Errorf

fmt.Errorf builds an error using Printf-style formatting, letting you embed dynamic values directly into the error message without a separate Sprintf call.

Note: fmt.Errorf is generally preferred over errors.New when the message needs any dynamic data.

Example: Creating Errors with fmt.Errorf

markup
package main

import "fmt"

func checkStock(item string, qty int) error {
	if qty <= 0 {
		return fmt.Errorf("item %q is out of stock", item)
	}
	return nil
}

func main() {
	if err := checkStock("widget", 0); err != nil {
		fmt.Println(err)
	}
}

The if err != nil Idiom

The standard Go pattern is to check the error result immediately after a call that might fail, and handle or propagate it before proceeding -- this makes failure paths explicit and impossible to silently skip.

Example: The if err != nil Idiom

markup
package main

import (
	"fmt"
	"strconv"
)

func main() {
	n, err := strconv.Atoi("not-a-number")
	if err != nil {
		fmt.Println("failed to parse:", err)
		return
	}
	fmt.Println("parsed:", n)
}
Common Mistakes
  1. Ignoring a returned error entirely (using _ or just not checking it) instead of handling or propagating it.
  2. Comparing errors with == when they were created dynamically, instead of using errors.Is for wrapped errors.
  3. Assuming errors.New(fmt.Sprintf(...)) is idiomatic instead of using fmt.Errorf directly, which supports %w for wrapping.
Chapter Summary
  • error is a built-in interface requiring one method: Error() string.
  • Functions that can fail conventionally return their result plus an error as the last return value.
  • errors.New and fmt.Errorf are the two common ways to create a simple error.
  • Checking 'if err != nil' immediately after a call is the standard Go error-handling idiom.
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.