In this tutorial, we will show you how to import a package on a specific version. Your code may occasionally require extra functions not available in your current application. In these circumstances, packages can be used to increase the sophistication of your software. Each file contained in a single directory on disk is represented by a package. Functions, types, and interfaces defined in a package can be used as references in other Go files or packages.
Method 1: Using the go get with Go modules
Syntax
go get [-d] [-f] [-t] [-u] [-v] [-fix] [build flags] [packages]
Usage
A module is a collection of Go packages stored in a file tree with a go.mod
 file at its root. The go.mod
 file defines the module’s module path, which is also the import path used for the root directory, and its dependency requirements, which are the other modules needed for a successful build. Each dependency requirement is written as a module path and a specific semantic version.
Get downloads of the packages named by the import paths, along with their dependencies. It then installs the named packages, like 'go install
'. The most current package version is always retrieved via the go get
command. It can be beneficial to update your software with any updates to earlier versions of the package that are still more updated than the one you are running. With the GO111MODULE=on
(the default in all cases from Go 1.16), you can follow these two steps when you want to get a specific version of a package. The first one is to list all the available versions of that package:
go list -m -versions github.com/gorilla/mux
The second is running the go get
command with your desired version:
go get github.com/gorilla/mux@v1.7.4
Method 2: Using the gopkg.in
The gopkg.in service provides versioned URLs that offer the proper metadata for redirecting the go tool onto well-defined GitHub repositories. Developers that choose to use this service are strongly encouraged to not make any backward incompatible changes without also changing the version in the package URL. This convention improves the chances that dependent code will continue to work while dependent packages evolve.
The number used in the gopkg.in
URL looks like "v1" or "v42", and represents the major version of the Go package. No incompatible changes should be done to the package without also changing that version so that packages and applications that import the package can continue to work overtime without being affected by broken dependencies.
For clarity, assume a repository containing the following tags or branches:
- v1
- v2.0
- v2.0.3
- v2.1.2
- v3
- v3.0
The following selectors would be resolved as indicated:
- pkg.v1 → tag or branch v1
- pkg.v2 → tag or branch v2.1.2
- pkg.v3 → tag or branch v3.0
gopkg.in/pkg.v3 → github.com/go-pkg/pkg (branch/tag v3, v3.N, or v3.N.M) gopkg.in/user/pkg.v3 → github.com/user/pkg (branch/tag v3, v3.N, or v3.N.M)
Method 3: Using the golang/dep
dep
 is a dependency management tool for Go. It requires Go 1.9 or newer to compile.
dep
, see the documentation.Briefly, the four states of the golang/dep:
- The current project's source code.
- A manifest - a file describing the current project's dependency requirements. In dep, this is theÂ
Gopkg.toml
 file. - A lock - a file containing a transitively-complete, reproducible description of the dependency graph. In dep, this is theÂ
Gopkg.lock
 file. - The source code of the dependencies themselves. In dep's current design, this is theÂ
vendor/
 directory.
The Gopkg.toml
file is initially generated by dep init, and is primarily hand-edited. It contains several types of rule declarations that govern dep's behavior. One of the rules is the dependency rules: constraints and overrides allow the user to specify which versions of dependencies are acceptable, and where they should be retrieved from. A full example (invalid, actually, as it has more than one version rule, for illustrative purposes) of either one of these stanzas looks like this:
[[constraint]]
# Required: the root import path of the project being constrained.
name = "github.com/user/project"
# Recommended: the version constraint to enforce for the project.
# Note that only one of "branch", "version" or "revision" can be specified.
version = "1.0.0"
branch = "master"
revision = "abc123"
# Optional: an alternate location (URL or import path) for the project's source.
source = "https://github.com/myfork/package.git"
Summary
In this tutorial, I have introduced several ways to import a specific version of a package. We can use the Go module with the go get command or use third-party package managements such as golang/dep
or gopkg.in
to handle the version of imported packages.
References
https://go.dev/blog/go116-module-changes
https://github.com/golang/go/wiki/Modules
http://labix.org/gopkg.in
https://github.com/golang/dep
How do I import a specific version of a package using go get?