How to organize Go (Golang) code
2020-04-04
version 0.2, 2023-04-05
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:
-
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. -
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. -
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. -
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
Examples:
Lib repo
Monorepo with a single go.mod
Examples:
Monorepo with multiple go.mod files
Examples:
Resources
Some resources with different views on the topic: