How to manage Golang with asdf
This document describes how we are using asdf and some troubleshooting steps
What is ASDF?
Besides being the home row of the left hand in the qwerty layout it is also a tool to manage runtime versions of multiple different tools. The home page for asdf is at https://asdf-vm.com/. While they support more than one type of tool we are only using it for golang.
Why ASDF?
To find out more on why asdf was chosen please read ADR 0056 - Use asdf to manage golang versions in development
Why asdf global golang <version>
?
We ran into an issue with asdf and pre-commit hooks. During the installation process of the pre-commit hooks golanglint-ci
requires use of go. Basically the install of golanglint-ci
happens outside of the milmove directory, which doesn't have .tool-versions
. So it depends on the global version of golang installed. Since this could be via brew, which has a newer version of golang than currently used on MilMove, or any number of other ways we are recommending using asdf global
config to configure the default for outside the project as well. This is not different than before the ADR 56 because we had been using brew
to install and pin golang globally on our laptops.
How to get up and running
Install asdf
Run brew install asdf
to install asdf, then add it to your shell's rc file. See Adding to your Shell from the asdf documentation.
Install golang plugin
Run asdf plugin add golang
to add the golang plugin. There are other plugins for asdf if you'd like to use it for other projects as well. Also has support for legacy_version_file
to look for things like .node-version
instead of just .tool-versions
.
Install the version of golang MilMove is using
Run asdf install
to install the binary for the currently required version of golang.
Configure global use of golang version
Run cat .tool-versions
or view the .tool-versions
file in your editor to output what version of go we should be using
Then run asdf global golang <version>
where <version>
is the version defined in .tool-versions
Reload your shell
Reload your shell, open a new shell or source your rc file.
Verify install
Run asdf current
and which go
to verify they point to the right versions. This is also checked by the script/prereqs
script
❯ asdf current
golang <version> /Users/john/projects/dod/mymove/.tool-versions
❯ which go
/Users/john/.asdf/shims/go
❯ rm .prereqs.stamp
❯ make prereqs
scripts/prereqs
/usr/local/bin/aws installed.
bash installed.
/usr/local/bin/chamber installed.
docker installed.
jq installed.
asdf installed.
.asdf/shims was found in path
go installed.
yarn installed.
pre-commit installed.
shellcheck installed.
psql installed.
nodenv installed.
.nodenv/shims was found in path
node installed.
pkcs11-tool installed.
pkcs15-tool installed.
circleci installed.
direnv installed.
entr installed.
aws-vault installed.
watchman installed.
OK: all prereqs found
Troubleshooting
GOROOT is showing a different version or not working with GoLand
Another issue GoLand users and others can run into with asdf is with GOROOT. Goland expects GOROOT to be set but it may be unclear what it should be set to. You can easily find the value by running asdf where golang
. Not upgrading versions will require this to change unless you can set GOROOT to the output directory of asdf where golang
. For example, you can set this in your ~/.zshrc
(or similar) shell:
export GOROOT="$(asdf where golang)/go/"
Missing asdf.sh
executable
Some users have run into an issue with not being able run asdf
. This is fixed by adding the following line to the .bash_profile
file:
source $(brew --prefix asdf)/libexec/asdf.sh
then run source ~/.bash_profile
in the terminal to reload.
Compile errors because wrong version of go after upgrading
If you are getting can't compile because library was compiled for old version of go
vs current version of go
. You probably should exit your shell and open a new one. Also ensure the below are in your shell's rc file.
# Ensure that the `asdf.sh` file is run first before invoking any `go *`
# commands.
source $(brew --prefix asdf)/libexec/asdf.sh
export GOPATH=$(go env GOPATH)
export PATH="$PATH:$(go env GOPATH)/bin"