Error-Handling

This lesson introduces error-handling in Go.

Introduction

Go does not have an exception-handling mechanism, like the try/catch in Java or .NET. For instance, you cannot throw exceptions. Instead, it has a defer-panic-and-recover mechanism. The designers of Go thought that the try/catch mechanism is overused and that the throwing of exceptions in lower layers to higher layers of code uses too many resources. The mechanism they devised for Go can ‘catch’ an exception, but it is much lighter. Even then, it should only be used as a last resort.

How then does Golang deal with normal errors by default? The Go way to handle errors is for functions and methods to return an error object as their only or last return value—or nil if no error occurred—and for the code calling functions to always check the error they receive.

Note: Never ignore errors because ignoring them can lead to program crashes.

Handle the errors and return from the function in which the error occurred with an error message to the user: that way, if something goes wrong, your program will continue to function, and the user will be notified. The purpose of panic-and-recover is to deal with genuinely exceptional (so unexpected) problems and not with normal errors.

Go makes a distinction between critical and non-critical errors: non-critical errors are returned as normal return values, whereas for critical errors, the panic-recover mechanism is used.

Library routines often return some sort of error indication to the calling function. In the preceding chapters, we saw the idiomatic way in Go to detect and report error conditions:

  • A function which can result in an error returns two variables, a value, and an error-code; the latter is nil in cases of success and != nil in cases of an error condition.
  • After the function call, the error is checked. In case of an error (if error != nil), the execution of the current function (or if necessary, the entire program) is stopped.

In the following code, Func1 from package pack1 is tested on its return code:

if value, err := pack1.Func1(param1); err != nil {
  fmt.Printf("Error %s in pack1.Func1 with parameter %v", err.Error(), param1)
  return // or: return err
} else {
   // process(value)
}

Always assign an error to a variable within a compound if-statement; this makes for clearer code.

Instead of fmt.Printf, corresponding methods of the log package could be used, or even a panic, if it doesn’t matter that the program aborts.

Go has a built-in error interface type:

type error interface {
  Error() string
}

Error values are used to indicate an abnormal state. The package errors contains an errorString struct, which implements the error interface. To stop the execution of a program in an error-state, we can use os.Exit(1).

error interface
errors.New(text string) error
err.Error() string

Defining errors

Whenever you need a new error-type, you can make one with the function errors.New from the errors package (which you will have to import), and give it an appropriate error-string, as follows:

err := errors.New("math - square root of negative number")

Below, you see a simple example of its use:

Create a free account to view this lesson.

By signing up, you agree to Educative's Terms of Service and Privacy Policy