If you are using an Apple Silicon M1 chip, then you may encounter an issue when downloading Go versions 1.15 or earlier via dl
.
Here are the solution:
$ GOARCH=amd64; go run golang.org/dl/go1.15@latest download
$ go install golang.org/dl/go1.15@latest
$ go1.15 version
go version go1.15 darwin/amd64
Note: You need the latest Go 1.22 installed on your machine.
Below are the steps detailing how I found it.
Try to Install In the Usual Way
I have a MacBook Pro with an M1 chip and arm64
architecture:
$ uname -m
arm64
The topic “Managing Go installations” describes how to install multiple versions of Go on the same machine. The main steps to install Go 1.15 are as follows:
- Install the
go1.15
program into the$GOBIN
directory:
$ go install golang.org/dl/go1.15@latest
$ ls $(go env GOBIN)
...
go1.15
...
- Download the binary:
$ go1.15 download
go1.15: download failed: no binary release of go1.15 for darwin/arm64 at https://dl.google.com/go/go1.15.darwin-arm64.tar.gz
When I first encountered this error, I created an issue for Go team: “dl: failed to install Go 1.15 on darwin/arm64”. Shortly after that, the maintainer wrote that this won’t be fixed as Go 1.15 is no longer supported. I need to think of the work-around.
The Go team states that any Go program you can compile for x86_64 should work on Arm. So, let’s build go1.15 for x86_64 and use it.
Work-around by Modifying the dl Binary
First, I investigated the dl
code by cloning it locally from the repo.
I found that the function versionArchiveURL
is responsible for downloading the archive of the given Go version.
Through trial and error, I found that adding this code leads to a successful result:
if goos == "darwin" && runtime.GOARCH == "arm64" {
if strings.HasPrefix(version, "go1.15") {
arch = "amd64"
}
}
The corrected and extended function code:
// versionArchiveURL returns the zip or tar.gz URL of the given Go version.
func versionArchiveURL(version string) string {
goos := getOS()
ext := ".tar.gz"
if goos == "windows" {
ext = ".zip"
}
arch := runtime.GOARCH
if goos == "linux" && runtime.GOARCH == "arm" {
arch = "armv6l"
}
if goos == "darwin" && runtime.GOARCH == "arm64" {
if strings.HasPrefix(version, "go1.15") {
arch = "amd64"
}
}
return "https://dl.google.com/go/" + version + "." + goos + "-" + arch + ext
}
We can build and run our custom binary:
$ cd go1.15
$ go build
$ ./go1.15
go1.15: not downloaded. Run 'go1.15 download' to install to /Users/Oleksandr_Redko/sdk/go1.15
And try to download:
$ ./go1.15 download
Downloaded 0.0% ( 16384 / 122458233 bytes) ...
Downloaded 4.8% ( 5914592 / 122458233 bytes) ...
Downloaded 12.0% ( 14696336 / 122458233 bytes) ...
Downloaded 29.1% ( 35684080 / 122458233 bytes) ...
Downloaded 47.6% ( 58326608 / 122458233 bytes) ...
Downloaded 70.7% ( 86605168 / 122458233 bytes) ...
Downloaded 83.9% (102792432 / 122458233 bytes) ...
Downloaded 97.6% (119569520 / 122458233 bytes) ...
Downloaded 100.0% (122458233 / 122458233 bytes)
Unpacking /Users/Oleksandr_Redko/sdk/go1.15/go1.15.darwin-amd64.tar.gz ...
Success. You may now run 'go1.15'
We can check the version:
$ ./go1.15 version
go version go1.15 darwin/amd64
Now, we can use the custom binary, ./go1.15
, to compile our old code.
However, modifying the dl’s code is too cumbersome. Can we find a better solution? Absolutely!
Better Approach by Setting GOARCH
We can try setting GOARCH=amd64
.
$ GOARCH=amd64; go install golang.org/dl/go1.15@latest
go: cannot install cross-compiled binaries when GOBIN is set
Unfortunately, another error occurred. This issue, “cmd/go: allow to install cross-compiled binaries when GOBIN is set” was already registered on the Go issue tracker in 2022 and seems not to have been resolved yet.
Final Solution
We know that we can compile and run a Go program in one command.
Let’s try:
$ GOARCH=amd64; go run golang.org/dl/go1.15@latest download
Downloaded 0.0% ( 16384 / 122458233 bytes) ...
Downloaded 18.7% ( 22888288 / 122458233 bytes) ...
Downloaded 37.7% ( 46153376 / 122458233 bytes) ...
Downloaded 64.5% ( 78953904 / 122458233 bytes) ...
Downloaded 87.3% (106921184 / 122458233 bytes) ...
Downloaded 100.0% (122458233 / 122458233 bytes)
Unpacking /Users/Oleksandr_Redko/sdk/go1.15/go1.15.darwin-amd64.tar.gz ...
Success. You may now run 'go1.15'
It should work:
$ go1.15 version
zsh: command not found: go1.15
The last thing is making available go1.15
command:
$ go install golang.org/dl/go1.15@latest
$ go1.15 version
go version go1.15 darwin/amd64
Success.
In the same way, we can download other versions: Go 1.14, 1.13, 1.12, and earlier, for which binary arm64 releases are not available:
$ GOARCH=amd64; go run golang.org/dl/go1.14@latest download
$ go install golang.org/dl/go1.14@latest
$ go1.14 version