Skip to main content

The GDS Way and its content is intended for internal use by the GDS community.

Go style guide

Note: Go is no longer a core language for backend development in GDS.

The purpose of this style guide is to provide some conventions for working on Go code within GDS. There are already good resources on writing Go code, which are worth reading first:

Code formatting

Use gofmt. This means all Go code reads in the same way which is important when looking at unfamiliar code.

You may also want to use golint which assesses code style.

Code checking

go vet, which checks correctness, should be used as part of your build process.

If you are writing concurrent code, use the race detector to detect race conditions.

External dependencies

As of Go 1.11 there is an officially developed module system, which is finalized in Go 1.13: go mod.

A historical pain point of development in Go was the manipulation of $GOPATH which is no longer required when using go mod.

There are several Go depency management tools in use at GDS, other than go mod:

  • dep (no longer in development)
  • godep (no longer in development)
  • glide (no longer in development)
  • gopkg.in, which provides a method of using versioned import paths
  • vendoring (ie copying source code in some manner to a location you control)

All new projects should use the officially developed go mod unless they have specific requirements not met by go mod

Vendoring is still common practice in Go, but if you are using go mod with Go 1.13+ then the go command will download and authenticate modules from the highly available Go module mirror and Go checksum database run by Google which alleviates the need to vendor your modules

Web frameworks

While it’s difficult to provide any guidance that will be generally applicable, there are couple of useful things to consider when structuring your Go program.

The first is that Go’s standard library is modern and powerful. If you just need simple HTTP routing and handling, the net/http package will probably meet your needs.

The second is that if net/http falls short, it’s worth choosing something that integrates well with it.

The third is that Go is not a language we use at GDS for developing fully-fledged web applications, eg rendering HTML. If you find yourself rendering HTML using Go, consider using a different GDS supported language.

Channels

Signalling

Channels that are being used purely for signalling should use an empty struct rather than boolean or int types.

Using an empty struct declares that we’re not interested in the value sent or received; only in its closed property.

See this talk

func worker(quit <-chan struct{}, result chan<- int) {
  for {
    select {
    case result <- rand.Intn(10000000):
    case <-quit:
      return
    }
  }
}

func main() {
  quit, result := make(chan struct{}), make(chan int)
  for i := 0; i < 100; i++ {
    go worker(quit, result)
  }
  // Wait for a worker to return a good result
  for {
    if <-result > 9999998 {
      break
    }
  }
  close(quit) // terminate all the workers
  fmt.Println("All done!")
}

Testing

There is some use across GDS of gomega for matching, and ginkgo for BDD testing.

If you find yourself writing too much boilerplate when testing Go, consider reaching for these libraries.

Gomega can help make your tests more readable:

err := doAThing() // this should fail
Expect(err).Should(HaveOccurred())

And Ginkgo can help set up a test suite:

var _ = Describe("Something", func() {
  It("should do a thing", func() {

    Expect("hi").To(HaveLen(2))

  })
})

which can be run with:

ginkgo

Tests can be focused (using regular expressions), to speed up development:

ginkgo -focus 'a thing'

Configuration parsing

There are a number of tools in use at GDS for parsing configuration and arguments:

  • alecthomas/kingpin (not actively maintained) for parsing simple command line arguments and environment variables
  • urfave/cli for building more advanced CLI tools
  • spf13/viper for parsing configuration files

These tools can make it easier to accept configuration parameters and help to make your application self-documenting.

This page was last reviewed on 23 April 2024. It needs to be reviewed again on 23 April 2025 by the page owner #golang .
This page was set to be reviewed before 23 April 2025 by the page owner #golang. This might mean the content is out of date.