Quick Introduction: Go Modules

Photo by Yusril Permana ali on Unsplash

The Go team introduced the package management feature Go Modules last year. This is a quick view of what it is and how to use it.

Go Modules

Before Go Modules proposal, we had to follow the $GOPATH based project layout. One of the biggest benefits of using Go Modules is that you can place your project anywhere you want.

It’s quite straightforward to start using it.

  • Create a project directory outside of $GOPATH. (If you want to enable go modules inside the $GOPATH, you need to set the go env var.)
  • Run go mod init <module name>. This command creates go.mod file, which is the list of all the dependencies.
  • Start writing your code as usual!

When you run commands such as go build, it runs go get looking at the dependencies in the code, updates go.mod file, and resolves dependencies using the following core concepts.

Semantic Import Versioning

is the concept that combines two ideas:

  • Semantic Versioning
  • Import Compatibility Rule

Probably you are already familiar with the first one. It’s just the widely accepted versioning convention shown in the following diagram.

From Semantic Import Versioning by @_rsc: https://research.swtch.com/vgo-import

The second one is the policy Go has been recommending as follows:

If an old package and a new package have the same import path,
the new package must be backwards compatible with the old package.

That means if you introduce incompatible changes to the existing package, you have to consider it as a different package, which results in putting version numbers in package paths.

By doing so, you can import the different versions of the same package just like this:

import (
"github.com/KentaKudo/hello/foo"
v2foo "github.com/KentaKudo/hello/v2/foo"
)

As a module author, there would be mainly two strategies to implement this.

  • The major branch strategy: implement v2 package in a different branch.
  • The major subdirectory strategy: implement v2 package under subdirectories.

For more details, see the following example:

Minimal Version Selection

is the algorithm to resolve dependency conflicts. Let’s say your module depends on module A and B. Module A depends on module C v1.0 and module B depends on C v1.2. In this situation if you run go get , Go installs v1.2 of module C the latest compatible version of the module. This selection algorithm gives the module “High-Fidelity Build”.

The details are in the RSC’s post:

Go Modules is well-designed to encourage the community to cooperate in solving the problem package management has by nature as explained in this talk, and as it’ll be used as a community standard as Go itself develops.

References

--

--