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):
cmd/ binaryname/ main.go # a small file glueing things together internal/ data/ types.go types_test.go # unit tests are right here (...) pkg/ api/ types.go # REST API input and output types test/ smoketest.py ui/ index.html README.md Makefile (...)
Go code lives in
pkg. Everything else has a clear place as well. Here’s why there are separate folders for subsets of
cmd directory contains subfolders with a single
main.go each. Each folder inside of
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!
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 directory contains packages which you might want to make accessible to other projects. It can have
subfolders by topic.
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.
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!