-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
2024-08-19/01: Add "Quick bits: Go automatically downloads a newer to…
…olchain if needed"
- Loading branch information
1 parent
5c595d3
commit ccd9ffe
Showing
1 changed file
with
73 additions
and
0 deletions.
There are no files selected for viewing
73 changes: 73 additions & 0 deletions
73
2024-08-19/01-quick-bits-go-automatically-downloads-a-newer-toolchain-if-needed.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# Quick bits: Go automatically downloads a newer toolchain if needed | ||
|
||
I am using | ||
[elliotchance/orderedmap](https://github.com/elliotchance/orderedmap/) as my | ||
choice of ordered maps (since Go [doesn't have | ||
one](/2024-08-17/01-an-unordered-list-of-things-i-miss-in-go.md) in standard | ||
library yet). I recently did a | ||
[PR](https://github.com/elliotchance/orderedmap/pull/41) to implement Go 1.23 | ||
iterators, because I find them neat, however I was avoiding to use it in the | ||
code that generates this [blog](https://github.com/thiagokokada/blog) since Go | ||
1.23 was just released and is still not the default Go in | ||
[nixpkgs](https://github.com/NixOS/nixpkgs). | ||
|
||
I decided that I would create a | ||
[branch](https://github.com/thiagokokada/blog/pull/2) and leave there for a few | ||
months, until I decided to try to run the code locally and got this: | ||
|
||
```console | ||
$ go build | ||
go: downloading go1.23.0 (darwin/arm64) | ||
``` | ||
|
||
Neat. And before you ask, yes, the compiled binary works perfectly: | ||
|
||
```console | ||
$ make | ||
./blog > README.md | ||
./blog -rss > rss.xml | ||
``` | ||
|
||
So how does this work? Take a look at the documentation in the official [Golang | ||
page](https://tip.golang.org/doc/toolchain): | ||
|
||
> Starting in Go 1.21, the Go distribution consists of a go command and a | ||
> bundled Go toolchain, which is the standard library as well as the compiler, | ||
> assembler, and other tools. The go command can use its bundled Go toolchain | ||
> as well as other versions that it finds in the local PATH or downloads as | ||
> needed. | ||
There are a bunch of rules here that I am not going to enter in detail (I | ||
recommend you to read the official documentation), but a quick summary: | ||
|
||
- Go will download a toolchain when either `go` or `toolchain` lines `go.mod` | ||
is set to a Go version higher than your current `go` binary | ||
+ But only if your `go` binary is at least version 1.21, since this is the | ||
version that introduces this behavior | ||
- You can force a specific toolchain with `GOTOOLCHAIN` environment setting, | ||
e.g.: `GOTOOLCHAIN=1.23` | ||
+ The default value for `GOTOOLCHAIN` is `auto`, that basically has the | ||
behavior described in this post | ||
+ You can also set to `local` to always use the current `go` binary, or the | ||
previous behaviour pre-1.21 Go | ||
+ There is also `<name>+auto` and `path` options, that can be seen in the | ||
docs | ||
- The downloaded toolchains go to whatever your `GOPATH` is, inside | ||
`golang.org/toolchain` module, and version `v0.0.1-goVERSION.GOOS-GOARCH`. | ||
|
||
By the way, this only works well because Go binaries are static, one of the | ||
things that make the language [reasonable | ||
good](/2024-07-29/02-go-a-reasonable-good-language.md). | ||
|
||
While I don't like a program downloading random binaries from the internet, I | ||
like what Go is doing here. It makes the whole bootstrapping process for a Go | ||
project much easier: as long as you have a reasonable up-to-date `go` binary in | ||
your `PATH`, you should be ready to go (pun intended). And Go modules are | ||
already reasonable secure, ensuring that each module have a proper checksum. As | ||
long as nobody else can publish modules in `golang.org/toolchain` namespace I | ||
can't see much of a security issue here, but I am not a security expert. | ||
|
||
But if you don't like this behavior, you can always disable it by setting | ||
`GOTOOLCHAIN=local`. And just do not forget to set this in your | ||
[CI](https://brandur.org/fragments/go-version-matrix), unless you don't care | ||
about Go versions. |