Find the Path to Go Module Major Versions With GoCenter

UPDATE: As of May 1, 2021 – GoCenter central repository has been sunset and all features will be deprecated. For more information on the sunsetting of the centers read the deprecation blog post

 

How many major versions of a given Go module are there? That simple question doesn’t always have an easy-to-discover answer.

Golang’s unique system of semantic import versioning solves some key problems of ensuring Go module compatibility across dependencies. But it also makes it a bit harder to learn what major versions of a Go module are available. The go client doesn’t provide a way to find out, nor will it inform you when a newer major version of a dependency exists.

If you simply want the absolutely latest version, how can you learn what or where that is?

GoCenter has a simple, but powerful new feature that helps developers know, for any Go module version, whether there are any other major versions available. It will also inform you of any alternative paths for that version. 

With this information, you can make the smartest choice about which version of a Go module to require as a dependency.

The Go module versioning system

With Go 1.13, modules have become the default dependency management for Go ecosystem.

Go module versions abide by the rules of semantic versioning, following the form v(major).(minor).(patch) :

  • MAJOR version when you make incompatible API changes,
  • MINOR version when you add functionality in a backwards compatible manner, and
  • PATCH version when you make backwards compatible bug fixes.

Within a major version, newer versions are expected to be backwards-compatible with earlier versions. For example, v1.2.3 must be compatible with v1.2.x but v2.x.x need not be compatible with any of those.

But Go module versions must also follow the import compatibility rule (formalized with Go 1.11) , which says:

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

This means that each Go module major version (for example, v1.x, v2.x, and v3.x) must occupy its own unique import path. By convention, Go module versions v0 and v1 occupy the base import path (i.e., the master branch of its source repo), while all module major versions v2 or higher include /vN at the end of the module path. (For Go module authors, I’ll describe this below.)

This Go module method for adhering to the rules of both semantic versioning and import compatibility is called semantic import versioning.

A variant of this path form is also recognized by the go client, and followed by the gopkg.in service. Here, the major version is identified in the import path by an extension suffix of the form .vN. For example, gopkg.in/yaml.v2.

GoCenter has a simple, but powerful new feature that helps developers know, for any Go module version, whether there are any other major versions available. Click To Tweet

The GoCenter Solution

GoCenter is the free central repository of over 1 million versioned Go modules. By setting your GOPROXY as follows:

$ export GOPROXY=https://gocenter.io


… your go client can resolve all open source Go module dependencies from this single, immutable, always-available repository.

GoCenter’s rich UI also enables you to search for the Go modules you need, and learn details about them through the rich, security-focused metadata stored with each version:

With GoCenter’s new feature, you can check the Other Paths Available dropdown to discover all other major version import paths, as well as any other import paths available for the same source.

For example, let’s look at the v1 Go module for Helm, the Kubernetes package manager. In addition to the helm.sh\helm import path we initially found, we can see that the import path helm.sh\helm\v3 is available to use Helm 3.

Helm major versions in JFrog GoCenter

GoCenter also lists as Other Paths all other import paths that have the same Helm v1 source.

Gocenter also supports major versions of modules in the gopkg.in domain that use the variant path form ( i.e. .vN at the end of module path). For example, the listing of the Go module for YAML v1 (gopkg.in/yaml.v1), identifies additional major versions for v2 and v3 (gopkg.in/yaml.v2, gopkg.in/yaml.v3).

GoPkg YAML major versions in JFrog GoCenter

Updating Go Dependencies for a New Major Version 

The go client provides a simple way to update your dependencies to the latest module versions, through the command go get -u. But this command will only download the new minor and patch changes of the specified major version.

There is no way for Go to automatically update your dependencies to use a new major version — and you wouldn’t want it to! Major revisions are, by definition, not backwards-compatible with prior major versions. Updating the major version reference alone would break your code!

Once you’ve found through GoCenter a new major version of a module that you want your code to use, you’ll need to review and update your Golang code for the API changes introduced by that major version.

Then you can update your Golang code’s dependencies to reference the new import path. GoCenter provides an easy way to get the full import path and version string into your clipboard:

Copy Go module path from JFrog GoCenter

In your codebase, you’ll need to find every import statement where that Go module is referenced, and update it for the new major version path.
For example, to update to Helm 3:

import “helm/helm.sh/v3”


If your Golang code is packaged as a Go module, you will also need to update the require statement in your go.mod file for the new import path, and also to specify the specific version number.

require helm.sh/helm/v3 v3.4.2

Creating New Module Versions

If you’re a Go module author, you’ll need to create a new major version of your module whenever you introduce a change that isn’t backwards compatible (such as a significant API change).

If you’re adopting modules for the first time for an existing repository or set of packages that have already been tagged v2.0.0 or higher, then the recommended best practice is to increment the major version when first adopting modules.

To create a new major version of your existing module, there are two ways to do it:

To maintain multiple major versions

Use this method if you want to maintain multiple major versions. To start development on a new major version (for example, v3), create a new v3 subdirectory in your master branch, and place a new go.mod file in that subdirectory. The module path must end with /v3. Copy the module code into the v3 subdirectory, and update relevant import statements within the module to also use the /v3 import path.

import “module github.com/myrepo/mymodule/v3/mypkg”


Tag the release with v3.x.y.

To maintain only current major versions

Use this method if you will only maintain current major versions. Update the current go.mod file to include /v3 at the end of the module path in the module directive.

module github.com/myrepo/mymodule/v3


Update import statements within the module to also use /v3 as shown in the first method. Tag the release with v3.x.y.

The Swift Road to GoCenter

Go modules continue to evolve, even now that they are the standard package management system for Golang. GoCenter evolves too, providing developers rich metadata that helps them to make the most of using these community Golang packages.

Explore GoCenter now to find out how this data-rich repository of immutable Go modules can help you deliver your apps fast and reliably!