Pin Go Installed Package Version
You may already have encountered the version issues when working with executable binaries installed by Go (using go install
command), specially if you’re working in a team, where other team members are using a different version of the same package that you’ve installed on your machine, and as a result, they get different outputs/results than what you get. In this post, I’m going to share a solution that I’m using. You can skip to the Solution section if you’re already familiar with this issue.
Problem
As you may know, Go command line provides the install
command, which as its documentation states:
Install compiles and installs the packages named by the import paths.
There are also many packages available by the Go community that needs to be installed to be used. Here are some of these packages that I usually use:
swag
: Generates Swagger/OAS documentation from code commentsmock
: Generates mock code that can be used for testingjet
: Generates type-safe models from existing SQL database schemas alongside provided utilities for writing SQL queries in Goeasyjson
: Generates code forstruct
s that does JSON serialization, and deserialization
Let’s take mock
package as an example, and have a simple Make
target similar to the following to make command execution easier:
.PHONY: gen
gen:
mockgen -source=foo.go
This has a couple of issues in general:
- It assumes the user has
mock
already installed on their machine, and it’s available in executables$PATH
, which is, in general, a bold assumption for a developer who joined recently for example. Or they do not want to include$GOBIN
directory in their$PATH
, maybe because there is an executables in their$GOBIN
that might mess up with the ones installed system-wide. - How would a developer know what is that
mock
executable, and where to install it from? Specially for some packages where their executable name differs from the package name, likemock
. It seems we need some sort of documentation here, right? - What if there is another executable named
mock
installed on your machine that gets executed instead of the one you installed usinggo install
? How would you resolve this? - What if the version resolved to the
latest
tag at the time of installation on my machine isv1.1.0
, for example, but versionv1.2.0
gets installed on CI environment tomorrow that causes some sort of misbehavior internally without any explicit errors on production?
Solution
The solution that I’m using recently is simply updating the command to the following:
.PHONY: gen
gen:
go run github.com/golang/mock/[email protected] -source=foo.go
It does the same thing without installing the executable in the $GOBIN
directory. Look at how explicit this version is, and we’d always want explicitness, don’t we?
How this works is it retrieves the specified version once, and builds it. Any subsequent execution of the same command will result in a cache-hit, and doesn’t require any downloads unless you change the version tag.