Minimalist Guide for Go Modules with Sub-Folders and Monorepos

By on September 6th, 2021

Original Go Directory Structure

When Go first came out, the default structure (on mac or linux) was to put all golang code into ~/go/src with a directory structure matching the import path. For example, a Go package import github.com/foo/bar would be at ~/go/src/github.com/foo/bar.

A sub-directory would be imported similarly, for example a package in the github repo foo/bar under a folder stuff/ would be imported using import github.com/foo/bar/stuff and live in the file system at ~/go/src/github.com/foo/bar/stuff.

Go modules allowed changing this semi-forced directory structure.

Go modules no longer require code to be at ~/go/src/.

Directory Structure for Monorepo-Style Go projects

It is still possible to use the original ~/go/src/ format, but no longer necessary.

Suppose you have a repository outside ~/go/src/, instead at ~/myproj/.

Suppose the directory ~/myproj/ is a repository at github.com/foo/myproj.

Inside it, you have several golang packages:

~/myproj/
~/myproj/gocode/helpers/http_services/get.go
~/myproj/gocode/helpers/databases/db_utils.go
~/myproj/gocode/app/main.go

What would the imports look like? How would the go modules be setup?

One option is to initialize the ~/myproj/gocode of the folder with:
go mod init github.com/foo/myproj which creates the file go.mod with the contents:

module github.com/github.com/foo/myproj
go 1.15

Now if you open up ~/myproj/gocode/app/main.go you can import the other services as follows:

import (
  "github.com/foo/myproj/helpers/http_services"
  "github.com/foo/myproj/helpers/database"
)

Note that the import path is relative to the go.mod file.

Final Thoughts

The above example is not necessarily a desired way to setup a package. It is an illustration of go mod flexibility.