Error handling and Go
12 Jul 2011
Tags: error, interface, type, technical

Andrew Gerrand

* Introduction

If you have written any Go code you have probably encountered the built-in `error` type. Go code uses `error` values to indicate an abnormal state. For example, the `os.Open` function returns a non-nil `error` value when it fails to open a file.

	func Open(name string) (file *File, err error)

The following code uses `os.Open` to open a file. If an error occurs it calls `log.Fatal` to print the error message and stop.

	    f, err := os.Open("filename.ext")
	    if err != nil {
	        log.Fatal(err)
	    }
	    // do something with the open *File f

You can get a lot done in Go knowing just this about the `error` type, but in this article we'll take a closer look at `error` and discuss some good practices for error handling in Go.

* The error type

The `error` type is an interface type. An `error` variable represents any value that can describe itself as a string. Here is the interface's declaration:

	type error interface {
	    Error() string
	}

The `error` type, as with all built in types, is [[https://golang.org/doc/go_spec.html#Predeclared_identifiers][predeclared]] in the [[https://golang.org/doc/go_spec.html#Blocks][universe block]].

The most commonly-used `error` implementation is the [[https://golang.org/pkg/errors/][errors]] package's unexported `errorString` type.

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

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

You can construct one of these values with the `errors.New` function. It takes a string that it converts to an `errors.errorString` and returns as an `error` value.

	// New returns an error that formats as the given text.
	func New(text string) error {
	    return &errorString{text}
	}

Here's how you might use `errors.New`:

	func Sqrt(f float64) (float64, error) {
	    if f < 0 {
	        return 0, errors.New("math: square root of negative number")
	    }
	    // implementation
	}

A caller passing a negative argument to `Sqrt` receives a non-nil `error` value (whose concrete representation is an `errors.errorString` value). The caller can access the error string ("math: square root of...") by calling the `error`'s `Error` method, or by just printing it:

	    f, err := Sqrt(-1)
	    if err != nil {
	        fmt.Println(err)
	    }

The [[https://golang.org/pkg/fmt/][fmt]] package formats an `error` value by calling its `Error()`string` method.

It is the error implementation's responsibility to summarize the context. The error returned by `os.Open` formats as "open /etc/passwd: permission denied," not just "permission denied."  The error returned by our `Sqrt` is missing information about the invalid argument.

To add that information, a useful function is the `fmt` package's `Errorf`. It formats a string according to `Printf`'s rules and returns it as an `error` created by `errors.New`.

	    if f < 0 {
	        return 0, fmt.Errorf("math: square root of negative number %g", f)
	    }

In many cases `fmt.Errorf` is good enough, but since `error` is an interface, you can use arbitrary data structures as error values, to allow callers to inspect the details of the error.

For instance, our hypothetical callers might want to recover the invalid argument passed to `Sqrt`. We can enable that by defining a new error implementation instead of using `errors.errorString`:

	type NegativeSqrtError float64

	func (f NegativeSqrtError) Error() string {
	    return fmt.Sprintf("math: square root of negative number %g", float64(f))
	}

A sophisticated caller can then use a [[https://golang.org/doc/go_spec.html#Type_assertions][type assertion]] to check for a `NegativeSqrtError` and handle it specially, while callers that just pass the error to `fmt.Println` or `log.Fatal` will see no change in behavior.

As another example, the [[https://golang.org/pkg/encoding/json/][json]] package specifies a `SyntaxError` type that the `json.Decode` function returns when it encounters a syntax error parsing a JSON blob.

	type SyntaxError struct {
	    msg    string // description of error
	    Offset int64  // error occurred after reading Offset bytes
	}

	func (e *SyntaxError) Error() string { return e.msg }

The `Offset` field isn't even shown in the default formatting of the error, but callers can use it to add file and line information to their error messages:

	    if err := dec.Decode(&val); err != nil {
	        if serr, ok := err.(*json.SyntaxError); ok {
	            line, col := findLine(f, serr.Offset)
	            return fmt.Errorf("%s:%d:%d: %v", f.Name(), line, col, err)
	        }
	        return err
	    }

(This is a slightly simplified version of some [[https://github.com/camlistore/go4/blob/03efcb870d84809319ea509714dd6d19a1498483/jsonconfig/eval.go#L123-L135][actual code]] from the [[http://camlistore.org][Camlistore]] project.)

The `error` interface requires only a `Error` method; specific error implementations might have additional methods. For instance, the [[https://golang.org/pkg/net/][net]] package returns errors of type `error`, following the usual convention, but some of the error implementations have additional methods defined by the `net.Error` interface:

	package net

	type Error interface {
	    error
	    Timeout() bool   // Is the error a timeout?
	    Temporary() bool // Is the error temporary?
	}

Client code can test for a `net.Error` with a type assertion and then distinguish transient network errors from permanent ones. For instance, a web crawler might sleep and retry when it encounters a temporary error and give up otherwise.

	        if nerr, ok := err.(net.Error); ok && nerr.Temporary() {
	            time.Sleep(1e9)
	            continue
	        }
	        if err != nil {
	            log.Fatal(err)
	        }

* Simplifying repetitive error handling

In Go, error handling is important. The language's design and conventions encourage you to explicitly check for errors where they occur (as distinct from the convention in other languages of throwing exceptions and sometimes catching them). In some cases this makes Go code verbose, but fortunately there are some techniques you can use to minimize repetitive error handling.

Consider an [[https://cloud.google.com/appengine/docs/go/][App Engine]] application with an HTTP handler that retrieves a record from the datastore and formats it with a template.

	func init() {
	    http.HandleFunc("/view", viewRecord)
	}

	func viewRecord(w http.ResponseWriter, r *http.Request) {
	    c := appengine.NewContext(r)
	    key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)
	    record := new(Record)
	    if err := datastore.Get(c, key, record); err != nil {
	        http.Error(w, err.Error(), 500)
	        return
	    }
	    if err := viewTemplate.Execute(w, record); err != nil {
	        http.Error(w, err.Error(), 500)
	    }
	}

This function handles errors returned by the `datastore.Get` function and `viewTemplate`'s `Execute` method. In both cases, it presents a simple error message to the user with the HTTP status code 500 ("Internal Server Error"). This looks like a manageable amount of code, but add some more HTTP handlers and you quickly end up with many copies of identical error handling code.

To reduce the repetition we can define our own HTTP `appHandler` type that includes an `error` return value:

	type appHandler func(http.ResponseWriter, *http.Request) error

Then we can change our `viewRecord` function to return errors:

	func viewRecord(w http.ResponseWriter, r *http.Request) error {
	    c := appengine.NewContext(r)
	    key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)
	    record := new(Record)
	    if err := datastore.Get(c, key, record); err != nil {
	        return err
	    }
	    return viewTemplate.Execute(w, record)
	}

This is simpler than the original version, but the [[https://golang.org/pkg/net/http/][http]] package doesn't understand functions that return `error`. To fix this we can implement the `http.Handler` interface's `ServeHTTP` method on `appHandler`:

	func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	    if err := fn(w, r); err != nil {
	        http.Error(w, err.Error(), 500)
	    }
	}

The `ServeHTTP` method calls the `appHandler` function and displays the returned error (if any) to the user.  Notice that the method's receiver, `fn`, is a function. (Go can do that!) The method invokes the function by calling the receiver in the expression `fn(w,`r)`.

Now when registering `viewRecord` with the http package we use the `Handle` function (instead of `HandleFunc`) as `appHandler` is an `http.Handler` (not an `http.HandlerFunc`).

	func init() {
	    http.Handle("/view", appHandler(viewRecord))
	}

With this basic error handling infrastructure in place, we can make it more user friendly. Rather than just displaying the error string, it would be better to give the user a simple error message with an appropriate HTTP status code, while logging the full error to the App Engine developer console for debugging purposes.

To do this we create an `appError` struct containing an `error` and some other fields:

	type appError struct {
	    Error   error
	    Message string
	    Code    int
	}

Next we modify the appHandler type to return `*appError` values:

	type appHandler func(http.ResponseWriter, *http.Request) *appError

(It's usually a mistake to pass back the concrete type of an error rather than `error`, for reasons discussed in [[https://golang.org/doc/go_faq.html#nil_error][the Go FAQ]], but it's the right thing to do here because `ServeHTTP` is the only place that sees the value and uses its contents.)

And make `appHandler`'s `ServeHTTP` method display the `appError`'s `Message` to the user with the correct HTTP status `Code` and log the full `Error` to the developer console:

	func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	    if e := fn(w, r); e != nil { // e is *appError, not os.Error.
	        c := appengine.NewContext(r)
	        c.Errorf("%v", e.Error)
	        http.Error(w, e.Message, e.Code)
	    }
	}

Finally, we update `viewRecord` to the new function signature and have it return more context when it encounters an error:

	func viewRecord(w http.ResponseWriter, r *http.Request) *appError {
	    c := appengine.NewContext(r)
	    key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)
	    record := new(Record)
	    if err := datastore.Get(c, key, record); err != nil {
	        return &appError{err, "Record not found", 404}
	    }
	    if err := viewTemplate.Execute(w, record); err != nil {
	        return &appError{err, "Can't display record", 500}
	    }
	    return nil
	}

This version of `viewRecord` is the same length as the original, but now each of those lines has specific meaning and we are providing a friendlier user experience.

It doesn't end there; we can further improve the error handling in our application. Some ideas:

- give the error handler a pretty HTML template,

- make debugging easier by writing the stack trace to the HTTP response when the user is an administrator,

- write a constructor function for `appError` that stores the stack trace for easier debugging,

- recover from panics inside the `appHandler`, logging the error to the console as "Critical," while telling the user "a serious error has occurred." This is a nice touch to avoid exposing the user to inscrutable error messages caused by programming errors. See the [[https://golang.org/doc/articles/defer_panic_recover.html][Defer, Panic, and Recover]] article for more details.

* Conclusion

Proper error handling is an essential requirement of good software. By employing the techniques described in this post you should be able to write more reliable and succinct Go code.
