How to organize Go (Golang) code

David Gamba, @gambaeng
2020-04-04
version 0.2, 2023-04-05 #development #golang

Recently my brother, who is coming from many years of Java coding, asked me how he should organize his Go code.

He was confused in part due to some official documentation that includes a src/ dir. The confusion and the reason for the documentation to exist in that form is because of the old $GOPATH where all different projects and repos would land in a single location.

With the advent of modules (and even before that, if you like me, used multiple dirs in your $GOPATH) it is much easier to talk about single repo code organization without considerations about where the rest of the go code in use in your computer lives.

This post will consider 4 repo structures that seem to work for me:

  1. Repo whose primary purpose is a cli tool, the package main will live at the root of the repo and the supporting packages as subfolders.

  2. Repo whose primary purpose is to be a library, the package libname will live at the root of the repo and a supporting cli tool will live in the cmd subfolder.

  3. Monorepo, multiple libs and cli tools live in a single repo with a single go.mod definition so all tools and libs share the same dependencies.

  4. Monorepo, multiple libs and cli tools live in a single repo each with their own go.mod definition so all tools and libs have independent lifecycles.

Common files

Regardless of your repo structure, these go at the root of each repo (or project):

go.mod

The modules

go.sum

The modules checksum.

Common directories

Regardless of your repo structure, these go at the root of your repo (or project):

vendor/

third party code you want to track locally outside of modules.

internal/

Internal only libraries that can’t be imported by other packages. There is no API guarantees and the compiler will fail if you try importing them.

CLI tool repo

Monorepo with a single go.mod

Monorepo with multiple go.mod files

Resources