How to structure a Go project?

Before getting back into developing professionally in Golang last year, I had so many questions:

  • What tools are useful?
  • What nuances am I missing?
  • What patterns are popular?
  • How to design testable applications?
  • What libraries are helpful when creating RESTful APIs?
  • How to make friends with interfaces and the Go-way of doing things?

Good ol’ A Tour of Go helped with the first one. The other ones took a bit of searching, watching talks, looking at projects and asking questions.

In hindsight, I’m really happy to have found a good answer to the topic of project and folder structure. It’s not that big of a thing, but having a clear way to structure new projects has helped me a lot. Once your folder structure is understandable, you can avoid unnecessary decisions while developing, keep an overview at all times and write code which is easier to get into for other people.

Here’s what I learned!

Why does structure matter?

A lightbulb moment for me, was thinking of folder structure as a user experience for people working on the project.

A good structure, can help to navigate the code, understand what’s important and to find the parts which are relevant to a developer’s current interests.

A good project structure will make it easier for your codebase to grow, and for new functionality to find a good place within it, without obscuring the older stuff. It will also make it easier for people who are relying on the code in other projects to have clear import paths.

The folder structure I stick to for now

Further down, I’ll list my favorite resources for this topic. If you want details, make sure to check them out!

If you just want to see my take a good-enough folder structure with some explanations to get started, read on.

My Go projects contain the following directories (with example .go files here and there):

    main.go # a small file glueing things together
    types_test.go # unit tests are right here
    types.go  # REST API input and output types

Go code lives in cmd, internal and pkg. Everything else has a clear place as well. Here’s why there are separate folders for subsets of .go files:

The cmd directory contains subfolders with a single main.go each. Each folder inside of cmd. If your project produces an executable binary, you will know exactly that your cmd folder will be the place to look. When you want to build or run something, it will look like go run cmd/binaryname/main.go - pretty obvious!

The internal folder contains packages which are specific to your project. They are not meant to be imported outside of this project, unlike the contents of the pkg folder.

The pkg directory contains packages which you might want to make accessible to other projects. It can have subfolders by topic.

Our test directory does not contain Go tests! Unit tests live right besides the code they are supposed to test. Instead, this is the place to put scripts for external blackbox and smoke tests. I like to use Python for my scripting needs, as you see.

The ui folder is used for the frontend part of the project. Templates, static assets or the project’s SPA can go here. In this case, I added be a single HTML file which is served straight out of the Go code.

Wait, what about GOPATH, src and all that?

One of my favorite changes in Go 1.11, was the addition of Go modules. They take godep’s job, and finally free your projects from having to be placed inside of the hierarchical complex folder structure of GOPATH. It’s super neat!

Cool resources to continue learning

Curious for more? There are a lot of great talks around that topic. Most of all, the GopherCon 2018 talk by Kat Zien has helped me a lot.

The guidelines around naming of Go package and file names, as well as naming in general were pretty neat. Having a good structure depends on a lot more than just the folder structure.

There’s a wonderful example project, which contains a lot of possible subdirectories, with great explanations. Check it out if you want more details!