Parellagram

Go and Errors as Values
March 26, 2016


I’ve been using Go a lot lately (if you haven’t noticed already). This website is written in it, and it has quickly become my favorite language. Many people disagree. The most common sticking point with newcomers is its error handling. After reading through the (excellent) (Go introduction)[https://tour.golang.org], people get often caught up with the following :

err := foo()
if err != nil {
    panic(err)
}
err = bar()
if err != nil {
    panic(err)
}
err = baz()
if err != nil {
    panic(err)
}

Or, if they’re fancy :

if err := foo() ; err != nil {
    panic(err)
}
if err := bar() ; err != nil {
    panic(err)
}
if err := baz() ; err != nil {
    panic(err)
}

Of course panic may be replaced with simply returning the error, or a call to log.Fatal. Rob Pike wrote a blog post about this, and this post will largely serve as simply another example or two. The long and short of it is that errors are values, so program them. Errors are not limited to being checked and returned. What does that mean? Let’s look at an example. In much the same vein as the example that Rob Pike uses, this website is generated by parsing a lot of templates. An initial approach (which I originally tried) would be something akin to the following:

tmpl := template.New("page")
if tmpl, err := tmpl.Parse(LANDING_PAGE_TEMPLATE) ; err != nil {
    return err
}
if tmpl, err := tmpl.Parse(STYLES_TEMPLATE) ; err != nil {
    return err
}
if tmpl, err := tmpl.Parse(POSTS_PREVIEW_TEMPLATE) ; err != nil {
    return err
}
if tmpl, err := tmpl.Parse(POST_PREVIEW_EMPLATE) ; err != nil {
    return err
}

Ugly, and more than enough to turn someone off of a new language. But this is if one only takes a look at a few examples, and assummes this to be the only way to process errors and handle these kinds of scenarios. However, to quote the much more eloquent Rob Pike, “errors are values and the full power of the Go programming language is available for processing them.” How does this translate into actual code?

I’m not aware of a name for this sort of pattern, but after discussing it with a friend of mine he suggested I call it the “Parella Pattern,” which I think we can all agree is a perfectly reasonable name. The idea is this : A closure wrapping around the error value allows us to call functions repeatedly and simply check for the error once at the end of the series of calls. The above example, in my code, has eventually settled on this :

tmpl := template.New("page")
var err error

parse := func(template string) {
    if err != nil {
        return
    }
    tmpl, err = tmpl.Parse(template)
}

parse(LANDING_PAGE_TEMPLATE)
parse(STYLES_TEMPLATE)
parse(POSTS_PREVIEW_TEMPLATE)
parse(POST_PREVIEW_TEMPLATE)

if err != nil {
    log.Fatal(err)
}

_ = tmpl.Execute(w, page)

The logic is easy to read, the error checking code is reduced to 1 (okay 2) if err != nil statements, and would remain so no matter how many templates we wanted to add. The code is also perfectly safe, if an error occurs in the first few parsing attempts, subsequent attempts will not hide this failure. This is important : this is not a way to avoid error checking, it is a way to do it simply, and cleanly.

This pattern winds up being applicable in a surprising amount of situations. Rob Pike’s article contains a few more. I’ve managed to work it in to many different situations, cutting down dramatically on unneeded boilerplate. We can switch over errors, use them as values in structs, anything we can do with other values because, of course : errors are values. And this is not a solution that is solely limited to Go. This can be applied to languages with exceptions or optional types, and in situations entirely unrelated to error checking. The “Parella Pattern” is very helpful. Hence the name.