Skip to content
Branch: master
Find file Copy path
Find file Copy path
1 contributor

Users who have contributed to this file

261 lines (188 sloc) 6.48 KB

Using submodules

Go modules supports nesting of modules, which gives us submodules. This example shows you how.

The resulting code can be found at


The official modules proposal predicts that most projects will follow the simplest approach of using a single Go module per repository, which typically means creating one go.mod file located in the root directory of a repository. However, there are cases when multiple modules in a single repository are worth the extra on-going work, and here we show a runnable example of how to create a multiple module repository with Go submodules.

Example Overview

The end result will be similar to the following, with three modules defined by the three go.mod files:

|-- go.mod
|-- b
|   |-- go.mod
|   `-- b.go
`-- a
    |-- go.mod
    `-- a.go

In this walkthrough:

  • We create a root module and two submodules.
  • We version the submodules independently by applying separate git tags (v0.1.1 and v1.0.0)
  • We have a import b to make things slightly more interesting.
  • We finish by creating a module on our local filesystem to use our a command.

Note that the root go.mod is optional here. (In general, you can have a multi-module repository without a root go.mod, and without any nesting of modules. The techniques shown in this example also apply to multi-module repositories that do not have any nested modules).


Initialise a directory as a git repo, and add an appropriate remote:

$ mkdir -p /home/gopher/scratchpad/submodules
$ cd /home/gopher/scratchpad/submodules
$ git init -q
$ git remote add origin

Define a root module, at the root of the repo, commit and push:

$ go mod init
go: creating new go.mod: module
$ git add go.mod
$ git commit -q -am 'Initial commit'
$ git push -q

Create a sub package b and test that it builds:

$ mkdir b
$ cd b
$ cat <<EOD >b.go
package b

const Name = "Gopher"
$ go mod init
go: creating new go.mod: module
$ go test
?	[no test files]

Commit, tag and push our new package:

$ cd ..
$ git add b
$ git commit -q -am 'Add package b'
$ git push -q
$ git tag b/v0.1.1
$ git push -q origin b/v0.1.1

Create a main package that will use b:

$ mkdir a
$ cd a
$ cat <<EOD >a.go
package main

import (

const Name = b.Name

func main() {
$ go mod init
go: creating new go.mod: module

Build and run that main package:

$ go run .
go: finding v0.1.1
go: downloading v0.1.1
go: extracting v0.1.1
$ go list -m v0.1.1

Notice how we resolve to the tagged version of package b.

Commit, tag and push our main package:

$ cd ..
$ git add a
$ git commit -q -am 'Add package a'
$ git push -q
$ git tag a/v1.0.0
$ git push -q origin a/v1.0.0

Create another random module and use our a command from there:

$ cd $(mktemp -d)
$ export GOBIN=$PWD/.bin
$ export PATH=$GOBIN:$PATH
$ go mod init
go: creating new go.mod: module
$ go get
go: finding v1.0.0
go: downloading v1.0.0
go: extracting v1.0.0
$ a

Version details

go version go1.12.5 linux/amd64
You can’t perform that action at this time.