Minimalist Guide for Go Modules with Sub-Folders and Monorepos

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.