Go Error Handling (Part 3) — The errors Package

Sher Chowdhury
3 min readDec 28, 2020
Photo by freestocks on Unsplash

The Go standard library's errors package makes it quick and easy to create error variables. Once the error variables are created, you can then use the if-statement pattern to decide what to do with it.

This article is part of the Error Handling in Go series.

The error’s package is a popular alternative to using Go’s built-in error type. That’s because using this built-in (interface) type requires a bit of leg-work, in terms of defining an error (struct) data type and a corresponding Error() method (as demoed in Part 2).

On the other hand, the errors package doesn’t require any of this extra setup; instead, you can go straight to creating error variables using the package’s errors.New() function.

https://play.golang.org/p/GPNGkQz2ssl

Line 4: We’re importing the errors package.

Lines 8–16: We created the lessThanTen function. This functions requires an integer argument and returns 2 output parameters, a string and an error value. This function completes successfully if you pass in an integer that’s less than 10, as indicated by the nil return value (line 11). If you pass in an invalid integer, i.e. an integer that’s 10 or greater, then the function fails and creates+returns an error value (line 14).

Tip: It’s best practice for functions to always return an error value. If your function has multiple return value’s then the convention is that the last output parameter should return the error value. This error value acts as indicator on whether the function ran successfully and it also lets you implement the follow on if-statement pattern.

Line 20: We call our function with a valid argument. This means that we get a nil error value so that the error-handling code block doesn’t get triggered (lines 22–23).

Line 27: We call our function again, but this time with an invalid argument. This time we do get an actual error value. This time the error-handling code block does get executed (lines 29–30).

Lines 29–30: The error-handling involves printing out the error value (line 29). However, as mentioned in Part 2 of this series, the fmt.Println tries to be helpful and automatically runs the err.Error() method instead. It the executes return (line 30). This return statement normally notifies the parent function that it has ended so that the parent functions continues. However, since in this example, the return function is executed in the top-level main function, it causes the program to exit.

Line 32: The program never reaches this line because it exited on line 30.

Another handy way to create an error is with the fmt package’s Errorf() function:

country := "Atlantis"
err := fmt.Errorf("The country, %s, does not exist" country)

This let’s you use the features of fmt.Sprintf() but to create an error object.

A closer look at the errors package

Ok, so far we’ve established that it’s easier to create error variables using the errors package, rather than using the built-in error type. But the truth is, we’re still using the built-in error type behind the scenes, via the errors package. If you take a look at the package’s source code, you’ll find that it defines a struct for storing errors and an Error() method for that struct:

  // errorString is a trivial implementation of error.
type errorString struct {
s string
}

func (e *errorString) Error() string {
return e.s
}

Don’t worry too much if this code block doesn’t make sense, that’s the beauty of Go packages, you can get away with using packages without needing to know about their inner workings. All good things come in small packages ;)

Further reading

--

--