Errors in Go - Beginner level

Navigating Go's Error Handling: A Beginner's Guide to Simplicity and Customization

Errors in Go - Beginner level

Photo by Nong on Unsplash

Play this article

TLDR;

This post delves into beginner-level error handling in Go. I will demonstrate Go's straightforward approach using the error value and emphasize the simplicity of handling errors with if statements. Custom error types, with examples, are introduced for enhanced debugging. This concludes with a teaser for upcoming topics like error wrapping and Is/As constructs as well.

Basics

In Go, errors are handled in an anachronistic way. Just like rust and C(go's predecessor) errors are returned from a function to a caller; this value is separate (error Value) then the intended type when the execution is succeeded. The following code example illustrates this fact...

func TryDivide(numerator, denominator int) (int, error) {
    if denominator == 0 {
        return 0, error.New("cannot divide by 0") // an error is returned
    }
    return numeraotr / denominator, nil // make error nill
}

In the above code following are to be derived:-

  • return type is a tuple with the last record being an error

  • when returning error, other records should be set to their zero values

  • error init by error.New() function

  • error messages should

    • start with lowercase

    • not to end with a newline or punctuation

Handling

Error handling in Go does not have any special constructs dedicated to it.

Check with if and proceed

res, err = TryDivide(10,3)
if err != nil {
    // logic to handle the error
    // usually program exits or returns error of its own.
}

// move on with business logic

The idiomatic way of handling an error:

  • inside if is what handles the error

  • outside if is continued business logic

By the above pattern, a reader can follow along the code base rather than having to switch between the branches. The latter is evident in languages that have a construct of try/catch blocks; this will introduce a new branch the code could develop often leading to complex control flow.

Custom Errors

often we may want to embed more information into error for later usage for debugging purposes. for example, we can include the parameters passed in or the environmental values configured at the time of the error etc;

as with other places, go error is just an interface with one requirement

type error interface {
    Error() string
}

error is often called this .Error() function which returns a string(message or anything). So to create a custom error type for web-server handlers or so we can embed the status code as well...

type ServerErr struct {
    code int
}

func (se ServerErr) Error() string {
    return fmt.Sprintf("error code was: %i", se.code)
}

Conclusion

this was a very quick rundown. There are other concepts to cover like:

  • wrapping

  • Is/As constructs

  • sentinel errors

But they are not necessary for basic usage; I will cover them later. If you want it already, let me know in the replies. I will post it immediately once I write it. Follow for more web development-related concepts.

Till then it's meTheBE, signing off.