What do the go and toolchain directives mean since Go 1.21, and how does GOTOOLCHAIN behave?
Since Go 1.21, go 1.22.0 is a strict minimum requirement (it used to be advisory). An older toolchain refuses to build the module, or downloads a newer one. The line also sets language semantics per module, for example loop-variable scoping, and which GODEBUG defaults apply. toolchain go1.23.4 is a preference for the main module only: the version to use when the local one is older. It never lowers the minimum.
go 1.22.0
toolchain go1.23.4
GOTOOLCHAIN=auto # default: local go, but switch up if go/toolchain line demands it
GOTOOLCHAIN=local # never download; fail if too old
GOTOOLCHAIN=go1.23.4 # force exactly this version
GOTOOLCHAIN=go1.23.4+auto # default to go1.23.4, switch up if go.mod requires newer
go get go@1.23.0 toolchain@go1.23.4 # bump deliberately
Toolchains are downloaded as modules (golang.org/toolchain) through GOPROXY and verified against the checksum DB.
Gotchas: if a dependency requires go 1.23, go get raises your go line too. Air-gapped CI with auto can fail with an attempted download, so set local and install the right version. Note the difference between 1.21 (a language version, satisfied even by go1.21rc1) and 1.21.0 (a release). go mod init and go get go@X write the full release form.
More on Modules, Packages & Tooling
- Q417Your CI can't fetch a private module from github.com/acme/secret. Walk through GOPROXY, GOPRIVATE, GONOPROXY, GONOSUMDB and GOINSECURE.
- Q418How does the Go checksum database protect the supply chain? What does go mod verify actually check?
- Q420What does this print? (Hint: consider the go line in go.mod.)
- Q421What does the Go 1.24 tool directive replace, and how do you use it?
- Q422What is the difference between go get and go install pkg@version in module mode?
- Q423Explain build constraints: the //go:build syntax, filename rules, and common gotchas.