What do the GOTOOLCHAIN values auto, local, path and go1.27.0 each tell the go command to do?
answer
- four kinds of value, not four flags
- one of them turns a switch into an error
- one of them refuses to download but will still change version
- there is a floor form written with a plus sign
- go env -w makes the choice stick
basics
~20 sGOTOOLCHAIN=auto uses the installed Go unless the module needs newer, then downloads it. local never switches and errors instead. path looks for an installed go1.x binary rather than downloading. A version name like go1.27.0 pins that exact toolchain.
solid answer
~40 s`auto` is the default in official releases: run the installed toolchain, and if go.mod or go.work demands newer, fetch that release and re-execute. `local` disables switching entirely — the installed toolchain is used and a module requiring newer fails with an error naming both versions and the setting. `path` behaves like auto but resolves the needed version from a `go1.x` binary on `PATH` instead of downloading one. A bare version, `go1.27.0`, pins that exact toolchain for every command regardless of what go.mod asks for, downloading it if absent. There are also floor forms, `go1.27.0+auto` and `go1.27.0+path`, meaning "at least this version, but still upgrade if required". You set it per command in the environment or persistently with `go env -w GOTOOLCHAIN=local`.
code
text · 3 lines$ go env -w GOTOOLCHAIN=go1.27.0
$ go env GOTOOLCHAIN
go1.27.0go deeper
Know that GOTOOLCHAIN exists, that auto is the default, and that setting it to local stops the go command from downloading and running a different Go version.
Be able to enumerate the value shapes and say precisely what each does when a module requires a newer release, including that path resolves from PATH rather than downloading and that a bare version name is an absolute pin.
Demonstrate that you know where the effective value is resolved from and how to inspect it on a machine you did not configure, and match each setting to an environment: laptop, CI image, release builder.
Frame the choice as a tradeoff between convenience and a build-time network dependency on an executable, and decide which environments get which value as a standard rather than per team.
## One variable, four shapes of answer `GOTOOLCHAIN` decides which Go toolchain actually executes a `go` command. It accepts four kinds of value, and the differences matter operationally because they trade silence for failure in different places. ### auto The default in official Go distributions. The go command uses the toolchain it is part of, unless the main module's `go` line, its `toolchain` line, or a workspace's `go.work` requires a newer release; then it obtains that release and re-executes as it. This is the setting that makes `git clone && go build` work on a machine whose installed Go is behind the repository. ### local Switching is off. The installed toolchain runs, always. If the module requires a newer Go, the command does not run at all: it errors with a message that names the required version, the version that is running, and the fact that `GOTOOLCHAIN=local` is in force. Nothing is downloaded and nothing is re-executed. Note the corollary: with `local`, a `toolchain` line in go.mod is inert — it is a preference about which release to switch to, and you have forbidden switching. The `go` line's requirement is still checked, because that is a hard minimum. ### path A middle position. Like `auto`, the go command is willing to move to a different version; unlike `auto`, it will not download one. Instead it looks along `PATH` for an executable named for the version it wants, in the `go1.x` form, and runs that. This suits a fleet where a configuration-management system installs approved toolchains and no build is allowed to pull an executable from the network. ### An explicit version name Setting `GOTOOLCHAIN=go1.27.0` pins that toolchain for every command in that environment. Whatever `go` binary you type, the named release runs — it is downloaded on first use if it is not present. This is the strongest form of pinning available and the usual choice for a build image where every job must use one known compiler. Because it is absolute, it does not chase a module that asks for something newer: such a build fails rather than upgrading. ### The +auto and +path floor forms `go1.27.0+auto` and `go1.27.0+path` say "never use anything older than this, and if something requires newer, get it (by download, or from PATH respectively)". These express a *minimum* org-wide toolchain while still letting an individual repository move ahead — useful when you want a security floor rather than an exact pin. ## Where the value comes from Precedence runs: the process environment first, then the go environment file written by `go env -w`, then the default compiled into the distribution. Official releases compile in `auto`; a repackaged Go may choose otherwise, which is a common reason two machines with nominally the same Go disagree. `go env GOTOOLCHAIN` prints the effective value after all of that resolution, which is why it, and not `echo $GOTOOLCHAIN`, is the right thing to collect from a machine. To change it persistently for a user or an image: `go env -w GOTOOLCHAIN=local` (or a version name). To change it for one command, set it in that command's environment. `go env -u GOTOOLCHAIN` removes the written value and restores the built-in default. ## Choosing between them The question behind the setting is: when a repository wants a compiler this machine does not have, what should happen? `auto` says "get it" — convenient, but the build silently depends on a network service and on an executable nobody vetted. `local` says "stop" — loud, reproducible, and it turns every version bump into a human action. `path` says "use one we installed" — the same loudness with a smoother upgrade path. A pinned version name says "this compiler and no other", which is what a release build usually wants. Most organisations end up mixing them: developer laptops on `auto`, build images pinned to a name, and the most sensitive environments on `local` or `path`.
- With GOTOOLCHAIN=local and a go.mod requiring a newer Go, what exactly do you see?The command refuses to run and prints an error stating that go.mod requires a newer version, alongside the version actually running and the fact that the setting is `local`. Nothing is downloaded. The fix is either to install a newer Go on that machine or to change the setting; the message deliberately names the setting so the cause is not a mystery.
- What is the difference between GOTOOLCHAIN=go1.27.0 and GOTOOLCHAIN=go1.27.0+auto?The bare name is an absolute pin: that release runs for every command, and a module requiring something newer fails. The `+auto` form makes it a floor — never run anything older, but still switch upward and download when a module requires a newer release. Pick the bare name for reproducible release builds and the floor form for a minimum-version policy.
- Why read go env GOTOOLCHAIN rather than the shell environment variable?Because the value can come from three places: the process environment, the file written by `go env -w`, and the default compiled into the distribution. Only `go env GOTOOLCHAIN` reports the effective result of that resolution. An unset shell variable tells you nothing about which of the other two is deciding.
saying these in an interview costs you the question
- Thinks local means use a local copy of the download
- Believes path points at a directory of toolchains
- Assumes an explicit version pin still upgrades when go.mod asks
- Says GOTOOLCHAIN is read only from the shell environment
- Claims local still honours the toolchain line in go.mod