How to Ship Production Grade Go 
5 Must-Haves for Robust, Debuggable Production Code

By Kavya Joshi

Shipping a production grade Go application is not the same as shipping a Go application. Remember, the big difference between your code and your code in production is all the ways it can fail; production grade code is code that recognizes that difference, and prevents or plans for it.

So, how can you convert your Go to production grade Go?

This article walks through five things to do to prime your code to run in production; the goal is for you to ship code that is robust, debuggable, and ready for the world.

Wrap Errors

Go applications in production may will encounter errors and panics. This section discusses how to write code that returns and handles errors usefully; the next section discusses panics. 

First off, write code that returns errors, rather than code that panics. Errors indicate abnormal state, whereas panics indicate unrecoverable conditions. Errors should be handled; panics should typically abort the program.

When you create or handle an error, annotate it with useful context for debugging. Dave Cheney’s errors  package is well-suited for this, and there are others you can use as well [1].

Here’s an example that uses the errors package for annotating errors:

  • Say you have a function getCount that returns an int and an error .
  • To create the error, use errors.New . It creates an error with the provided message and annotates it with a stack trace at that point.

// Import Dave Cheney's errors package

func getCount(key) (int, error) {
  if key <= 0 {
    // Create an annotated error.
    err := errors.New("invalid key")
    return 0, err    
  return count, nil

  • Now, say getCount is called by a function  canProceed .
  • canProceed checks the error and if it’s non-nil , handles it or propagates it:

func canProceed(key int) bool {
  count, err := getCount(key)
  if err != nil {
    // Handle or propagate err.
  } else {
    return count < threshold

The footnote discusses how to choose between handling an error or propagating it [2]. For now, let’s look at examples of how to do both in a useful manner with the errors package.