Skip to content
Latchkey

goenv: Manage Go Versions in CI

goenv install <version> installs a Go toolchain and goenv local writes .go-version, with shims pointing go at the selected version and setting GOROOT.

goenv brings the rbenv shim model to Go. It manages GOROOT for you, which is the main thing to get right in CI because many Go tools resolve the standard library through it.

What it does

goenv installs multiple Go versions and switches between them with shims. It selects the version from .go-version (local), the global setting, or GOENV_VERSION, and points GOROOT at that install so the standard library matches the active toolchain.

Common usage

bash
export GOENV_ROOT="$HOME/.goenv"; export PATH="$GOENV_ROOT/bin:$PATH"
eval "$(goenv init -)"
goenv install 1.22.3
goenv local 1.22.3            # writes .go-version
go version

Options

Command / flagWhat it does
goenv install <v>Install a Go version
goenv install -s <v>Skip if already installed
goenv local <v>Write .go-version for this directory
goenv global <v>Set the default Go version
GOENV_GOPATH_PREFIXControl GOPATH layout per version
eval "$(goenv init -)"Add shims and manage GOROOT

In CI

Eval goenv init - in each step so GOROOT and PATH are set. Cache ~/.goenv/versions. Note that Go 1.21+ also has a built-in toolchain mechanism (the go directive in go.mod can auto-download a newer toolchain), which can interact with goenv; set GOTOOLCHAIN=local if you want goenv to be the only thing choosing the version.

Common errors in CI

"goenv: go: command not found" means init was not eval'd (shims/PATH not set). "version 1.22.3' is not installed" means the pin is uninstalled; run goenv install. A build using an unexpected Go version may be Go 1.21+ auto-downloading a toolchain per go.mod; set GOTOOLCHAIN=local`. Wrong stdlib errors usually mean GOROOT was set manually and conflicts with goenv.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →