Errors

What's going wrong with the code?

2-minute read
Table of Contents

As opposed to other languages like Python and JavaScript that use a try-catch approach to error handling, Go encourages us to return a separate value that will indicate that the code did not perform in an ideal manner - an error.

This way of handling errors ensures that dealing with errors are part of the normal execution flow of the code, instead of having a structure that can be completely left out, as is the case of a try-catch.

Convention

It is customary to return the error as the last value from a function, with the return type being error:

package main

import (
	"errors"
	"fmt"
)

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

func main() {
	numbers := []int{3, 2, 0, -4, 5, -2}
	for _, f := range numbers {
		result, err := Div(4.0, float64(f))
		if err != nil {
			fmt.Printf("error: %v\n", err)
		} else {
			fmt.Printf("4/%d = %f\n", f, result)
		}
	}
}
errors-new.go
Copy

The function errors.New() is used to define a new error with a desired error message. We can use the fmt.Errorf function to define errors as variables in our code:

package main

import (
	"fmt"
)

var ErrNoZeroDivision = fmt.Errorf("cannot divide by zero")

func Div(a, b float64) (float64, error) {
	if b == 0.0 {
		return 0.0, ErrNoZeroDivision
	}
	return a / b, nil
}

func main() {
	numbers := []int{3, 2, 0, -4, 5, -2}
	for _, f := range numbers {
		result, err := Div(4.0, float64(f))
		if err != nil {
			fmt.Printf("error: %v\n", err)
		} else {
			fmt.Printf("4/%d = %f\n", f, result)
		}
	}
}
errors-fmt.go
Copy

Inline checking

We can check errors inline by separating the lines using a semi-colon:

package main

import (
	"fmt"
)

var ErrNoZeroDivision = fmt.Errorf("cannot divide by zero")

func Div(a, b float64) (float64, error) {
	if b == 0.0 {
		return 0.0, ErrNoZeroDivision
	}
	return a / b, nil
}

func main() {
	numbers := []int{3, 2, 0, -4, 5, -2}
	for _, f := range numbers {
		if result, err := Div(4.0, float64(f)); err != nil {
			fmt.Printf("error: %v\n", err)
		} else {
			fmt.Printf("4/%d = %f\n", f, result)
		}
	}
}
errors-inline.go
Copy

Our code can look more compact using this technique.

Custom errors

Any custom type can be used as an error as long as it implements the Error() method.

Support us via BuyMeACoffee