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!
An overview of forms
First, check out this page from the Go documentation.
It lists a few valid layouts for a Go module (aka project) - a lot of forms are considered to be good! From very simple, to slightly more complicated. One binary or multiple ones.
Everything starts with the least amount of fuzz and can become more complicated as required. The documentation page above is a great resource!
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 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
As mentioned initially, the Go docs have a great page about this topic
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.
Note: the following project is somewhat controversial, and it seems like many people do not consider it to be standard at all, contrary to the name. I still find it helpful, even though to be taken with a grain of salt.
There’s a wonderful example project, which contains a lot of possible subdirectories, with great explanations. Check it out if you want more details!