Go Modules is the official dependency management solution for the Go programming language. Recently, I finally converted over my personal projects. I had been putting it off for some time, since I was waiting for the Go team to finalize everything and work out all the kinks. Go 1.11 was when Modules was first released as a beta. Go 1.12 still had Modules in beta mode and Go 1.13 was when Modules came out of beta. After Go 1.14 came out, I figured it was probably time to transition over from dep (which is deprecated now). It was a mostly smooth experience, but I did run into some snags. For example, upgrading a package that has already had its major version incremented to 2 or greater requires a bit more work. In an effort to share my findings, here are some common commands I found useful.

Initialize a new module

This command is only used once to create a new module or to convert an existing package. It creates a new go.mod file. If the package was previously using some other form of Go dependency management, it should automatically determine dependencies based on the previous tool. For example, my projects used dep and Modules locked dependencies based on dep’s Gopkg.toml.

go mod init

Tidy up dependencies

This is the go-to command that should be run any time changes are made to a project. This command will add missing dependencies or remove extraneous dependencies. It ensures the go.mod file matches the dependencies a package is actually using.

go mod tidy

Vendor all dependencies

The general consensus among the Go community is that vendoring is no longer needed and we can rely on the Go module proxy to store dependency versions. For those that still desire to vendor their dependencies, modules provides the capability to copy all modules referenced in your project to the vendor folder using the following command:

go mod vendor

Update dependencies

Updating dependencies is integrated with the go get command in the standard Go toolchain. This command will update a singular dependency:

go get -u github.com/eleniums/async

Update a dependency to a specific version:

go get github.com/eleniums/async@v2.2.0

This command will update ALL dependencies in your package:

go get -u ./...

Determine how a dependency is referenced

Figure out how a dependency is used:

go mod why -m github.com/eleniums/async

Another method for determining how a dependency is used:

go mod graph | grep github.com/eleniums/async

This command will list all direct dependencies of a module:

go list -m -f '{{if not .Indirect}}{{.Path}}{{end}}' all

Delete modules cache

You shouldn’t typically need to clear the module cache, but in the event something goes horribly wrong and Modules is unable to recover, it’s useful to know how to clear the cache and start fresh.

go clean -modcache

Convert an existing package to Modules

I found it was really easy to convert an existing v1 package to Modules. The process was simple:

  • Run go mod init
  • Remove old dependency management files (Gopkg.toml and Gopkg.lock for dep)
  • Increment the minor version (recommended)

But what to do if a package is already on v2 or beyond? One of the design philosophies behind Go is backwards compatibility. Modules was designed with this in mind and can actually support multiple major versions of the same module side by side. Unfortunately, it basically expects you to still be on v1 when you convert to Modules. If you are on major version 2 or greater, Modules expects v2 (or v3, etc.) to be part of the package path. There are some ways around this, but I found them to not be desirable and it was easier to just bite the bullet and create a full major version upgrade. The general steps for a major version Modules conversion:

  • Run go mod init
  • Remove old dependency management files (Gopkg.toml and Gopkg.lock for dep)
  • Increment the minor version (recommended)
  • Copy code files to new v2 folder
  • Copy go.mod and go.sum files to v2 folder
  • Adjust module path in v2/go.mod to include /v2 at the end

For an example of a converted package with a major version of 2 or greater, take a look at one of the following projects:

References

Here are some links that I found useful when learning about Go Modules: