How To

Install Go (Golang) on Linux Mint 22

You can install Go on Linux Mint three ways, and the obvious one gives the oldest compiler. On Mint 22, the stock golang-go package pulls Go 1.22 from the Ubuntu noble archive, five minor versions behind the current upstream release. The longsleep PPA sits in between, and Snap, which older guides recommend, is blocked by default on Mint.

Original content from computingforgeeks.com - post 7587

Our pick is the official tarball from go.dev, unpacked to /usr/local/go. It is the current release, you can check it against the go.dev checksum manifest, and upgrading is the same three commands again. This guide covers that path first, then the apt and PPA routes and the toolchain auto-download that makes the old apt package more usable than it looks. Everything was run on Linux Mint 22.3 (noble base, kernel 6.14) in October 2026, with Go 1.27.2 from go.dev and Go 1.22.2 from the Mint repositories.

Choose how to install Go

The right method depends on whether you need the current Go or just a Go. Most module code on GitHub now declares a recent go line in its go.mod, so an old compiler either downloads a newer toolchain on the fly or refuses to build. Mint 22 inherits its Go packages from the Ubuntu 24.04 base, as the Ubuntu and Linux Mint comparison explains, so apt gives you whatever noble shipped. Each option gave us something different on Mint 22.3.

MethodGo version you getHow it updatesOur verdict
Official tarball (go.dev)1.27.2, current releaseRepeat the download and extractRecommended
apt golang-go1.22.2apt, stays on 1.22Fine for old projects, leans on toolchain downloads
apt golang-1.26-go1.26.8apt (noble-updates)Listed, not installed in our test
longsleep PPAgolang-go 1.26, golang-1.27-go 1.27.2aptWorks, adds a third-party repo, needs a PATH line
SnapNonen/aBlocked by default on Mint

Start from what you build, not from which method looks easiest:

  • Current projects or code from GitHub: the tarball
  • One old project that pins Go 1.22: apt golang-go
  • Newest Go but updates through apt: the PPA’s golang-1.27-go

Snap is out because Mint ships an apt preference that pins snapd to priority -10, so on a default install sudo apt-get install -y snapd fails with “Package ‘snapd’ has no installation candidate”. You could undo that pin, but adding snapd to Mint for one compiler is a lot of machinery for something a tarball does in a minute. If you came here from the Go install on Ubuntu 26.04, note that Mint 22 is built on Ubuntu 24.04, so its archive versions are older than the ones that page shows.

Install Go from the official tarball

Check for an existing Go first. The apt package installs /usr/bin/go, and because the PATH line below appends /usr/local/go/bin at the end, the old apt binary would keep winning over the tarball:

which go || echo "no go on PATH"

On a clean machine this prints no go on PATH, which is what we got after removing the apt package. If it prints /usr/bin/go instead, remove the apt Go with the commands in the upgrade and removal section at the end of this guide, then come back here. Once the path is clear, the install itself takes four steps.

go.dev publishes the current version as plain text at a stable URL, so you never have to edit a version number into the commands. Read it into a variable first, because the download, the checksum and the extract all use it. Every later command in this section reads $GO_VER, so run them all in the same terminal.

GO_VER=$(curl -s "https://go.dev/VERSION?m=text" | head -1)
echo $GO_VER

It should print a single version string with the go prefix. If it prints nothing or an HTML page, your proxy or DNS is getting in the way, and the download below would fail the same way.

go1.27.2

Download the amd64 tarball into /tmp. We only tested amd64, so an ARM board would need the linux-arm64 file instead, and the checksum step would need the same change. The -f flag makes curl fail on an HTTP error instead of saving an error page under the tarball’s name.

cd /tmp && curl -fsSLO "https://go.dev/dl/${GO_VER}.linux-amd64.tar.gz"

Check the file before you unpack it into a system directory. The same go.dev download page serves a JSON manifest with the SHA-256 of every file, so this pulls the expected hash for your exact tarball and hands it to sha256sum. The one-liner only uses the Python standard library, and Mint ships python3 by default.

curl -s "https://go.dev/dl/?mode=json" | python3 -c "import json,sys; v=sys.argv[1]; print(next(f[\"sha256\"] for r in json.load(sys.stdin) for f in r[\"files\"] if f[\"filename\"]==v+\".linux-amd64.tar.gz\"))" $GO_VER > go.sha

That saves the published hash in go.sha. Feed it to sha256sum next to the file name:

echo "$(cat go.sha)  ${GO_VER}.linux-amd64.tar.gz" | sha256sum -c

A good download prints the file name followed by OK. Anything else means a broken or tampered download, so delete the file and fetch it again before going further. Don’t skip this, because the tarball goes straight into a root-owned directory on every user’s PATH.

go1.27.2.linux-amd64.tar.gz: OK

Now extract it to /usr/local. The rm -rf comes first on purpose, because Go’s install docs warn against unpacking a new release over an old /usr/local/go, since leftover files from the previous version can break the build.

sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf ${GO_VER}.linux-amd64.tar.gz
/usr/local/go/bin/go version
du -sh /usr/local/go

The binary runs straight from its full path, and the whole install takes 283 MB. Nothing outside /usr/local/go was written, which is what keeps upgrades and removal simple later.

go version go1.27.2 linux/amd64
283M	/usr/local/go

At this point Go is installed but only reachable by its full path, which is what the next step fixes.

Add Go to your PATH

Typing /usr/local/go/bin/go every time isn’t practical, so put the Go directory on the PATH for every user. A file in /etc/profile.d/ does that system-wide, and the second path, $HOME/go/bin, is where go install drops the tools you install later.

echo "export PATH=\$PATH:/usr/local/go/bin:\$HOME/go/bin" | sudo tee /etc/profile.d/go.sh

Check it from a fresh login shell, since login shells are the ones that read /etc/profile.d. Running the check through bash -lc tests exactly that without logging out of your session.

bash -lc "go version; go env GOROOT GOTOOLCHAIN"

A login shell finds the new Go, with GOROOT pointing at /usr/local/go and the toolchain mode left at its default. That default, GOTOOLCHAIN=auto, means this Go will also fetch a newer toolchain when a project asks for one, which the apt section below shows in action.

go version go1.27.2 linux/amd64
/usr/local/go
auto

A terminal that was already open won’t see it. In our test an interactive non-login shell (bash -ic "go version") still failed with exit code 127, command not found, because only login shells read /etc/profile.d. Log out of the Mint desktop and back in, which starts a login session that reads the file. Until then, paste export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin into the terminal you are using.

Build a test program

A compiler that prints its version can still be broken in the ways that matter, like fetching modules or writing binaries, so build something. Create a module in your home directory.

mkdir ~/hello && cd ~/hello
go mod init example.com/hello
cat go.mod

The block shows the file go mod init wrote; its own one-line status message was hidden in our run. go mod init stamps the module with the version of Go that created it. That go line is what an older compiler checks later, which matters if you ever share this code with someone on the apt package. A colleague on Mint’s 1.22 compiler would either download the newer toolchain automatically or, with auto-download disabled, get a refusal to build. The toolchain errors further down come from exactly that situation.

module example.com/hello

go 1.27.2

Next comes the program itself. Open a new main.go in the module directory, which is all a single-file Go program needs.

vim main.go

Add this program, which only prints one line so that any failure points at the toolchain and not the code:

package main

import "fmt"

func main() { fmt.Println("Hello from Linux Mint") }

Run it, then build a standalone binary and check its size. go run compiles to a temporary file, while go build leaves the binary in the current directory.

go run .
go build -o hello . && ls -lh hello

It prints its line and the static binary comes out at 2.3 MB, with no runtime to install on the machine you copy it to:

Go from the official tarball building a hello module in ~/hello on Linux Mint 22.3

The last check is go install, which downloads a module, builds it and puts the binary in ~/go/bin. That is the directory the profile.d file added to your PATH, so tools you install this way run by name. We used the small HTTP load generator hey:

go install github.com/rakyll/hey@latest
command -v hey

It pulls its dependencies through the Go module proxy and lands in your home directory (the output below is trimmed to the last download line). The first go install also creates ~/go/bin, which is why the PATH line could name it before it existed.

go: downloading golang.org/x/text v0.33.0
/home/josphat/go/bin/hey

If command -v hey prints nothing, the second half of the PATH line is not loaded yet, which is the logout issue from the previous section, and a fresh login fixes it without reinstalling anything. For an editor, our guide to Visual Studio Code on Linux Mint pairs well with the Go extension.

Use the Mint repository Go instead

Mint’s own package is one apt command and updates with the rest of the system, which is a fair reason to pick it. The catch is the version. On Mint 22.3 golang-go resolves to the 1.22 line from the noble archive.

sudo apt-get install -y golang-go
go version
readlink -f $(which go)

The go on your PATH is a symlink into a versioned directory under /usr/lib, which is how Ubuntu keeps several Go releases installable side by side. Remember that path, because the version directory is what changes if you later switch to another golang package.

go version go1.22.2 linux/amd64
/usr/lib/go-1.22/bin/go

That is older than most current projects ask for, but the package ships with GOTOOLCHAIN=auto in /usr/lib/go-1.22/go.env, and that setting changes the picture. When a go.mod requires a newer release, the 1.22 compiler downloads the right toolchain from the Go module proxy and hands the build to it. To see it, we made a throwaway module in /tmp/gt whose go.mod requires the newer release.

mkdir /tmp/gt && cd /tmp/gt
vim main.go

The program prints the version of the toolchain that actually built it, which is the whole point of the test:

package main

import ("fmt"; "runtime")

func main() { fmt.Println("built with", runtime.Version()) }

Then create the go.mod next to it, in the same directory, so the 1.22 compiler sees a newer requirement than it can meet on its own.

vim go.mod

The file holds a module path and a go line with the full patch version. The patch number matters, as the first error below shows.

module example.com/gt

go 1.27.0

With both files in place, the first go run . took 20.6 seconds while it fetched the toolchain, and the build reported the newer Go:

Linux Mint golang-go package downloading a newer Go toolchain for a go.mod on Linux Mint 22.3

Downloaded toolchains live in the module cache, so they cost disk space rather than a system install. We measured it with du.

du -sh ~/go/pkg/mod/golang.org/toolchain*

One toolchain took 253 MB, nearly as much as the full tarball install. Each further release a project asks for adds another directory of about the same size.

253M	/home/josphat/go/pkg/mod/golang.org/[email protected]

Only that module gets the switch. Run go version in any other directory and you’re back on the 1.22 compiler, so every project quietly carries its own compiler. That works, but each new release a project asks for is another quarter gigabyte in your cache and another 20 second wait on its first build. If you work on more than one current project, the tarball is less hassle.

go: download go1.27 for linux/amd64: toolchain not available

This is the error the 1.22 auto-download hits when go.mod says go 1.27 without a patch number. Our first test file had exactly that line, and the compiler tried to fetch a toolchain called go1.27, which doesn’t exist on the proxy, because releases are published as go1.27.0, go1.27.1 and so on. Go 1.23 and newer map a bare go 1.27 to go1.27.0 on their own (golang/go issue 62278), so the error belongs to Mint’s 1.22 package, which predates that change.

go: downloading go1.27 (linux/amd64)
go: download go1.27 for linux/amd64: toolchain not available

Changing the line to go 1.27.0 fixed it, which is the run shown above. You can make the same edit with sed.

sed -i "s/^go 1.27$/go 1.27.0/" go.mod

Any local Go from 1.23 on avoids it without touching the file, because those releases translate the short form before they ask the proxy. That’s one more argument for the tarball on a machine where you build other people’s code.

go: go.mod requires go >= 1.27 (running go 1.22.2; GOTOOLCHAIN=local)

You get this when the auto-download is turned off, either by GOTOOLCHAIN=local in your environment or in go env. The old compiler refuses to build rather than fetch anything. Either unset it, or install a Go that meets the requirement, since forcing an old compiler on code that declares a newer version is not supported.

Ubuntu’s noble archive also carries versioned packages such as golang-1.26-go. apt-cache policy listed them from noble-updates and noble-security, but we didn’t install one, so we can’t tell you how they set up the PATH.

apt-cache policy golang-1.26-go golang-1.25-go

Both candidates come from the official Ubuntu mirrors that Mint uses.

golang-1.26-go:
  Candidate: 1.26.8-1~ubuntu0.24.04.2
     1.26.8-1~ubuntu0.24.04.2 500
        500 http://archive.ubuntu.com/ubuntu noble-updates/universe amd64 Packages
        500 http://security.ubuntu.com/ubuntu noble-security/universe amd64 Packages
golang-1.25-go:
  Candidate: 1.25.14-1~ubuntu0.24.04.1
     1.25.14-1~ubuntu0.24.04.1 500
        500 http://archive.ubuntu.com/ubuntu noble-updates/universe amd64 Packages
        500 http://security.ubuntu.com/ubuntu noble-security/universe amd64 Packages

Those packages track the 1.26 and 1.25 lines, so even the newest one in the archive is a release behind go.dev.

Add the longsleep golang-backports PPA

The longsleep PPA rebuilds newer Go releases for Ubuntu, and Mint’s add-apt-repository handles it fine. It writes a signed source for the noble series.

sudo add-apt-repository -y ppa:longsleep/golang-backports
cat /etc/apt/sources.list.d/longsleep*
sudo apt-get update

Its source line points at the noble suite with its own keyring, so the PPA key is trusted for this repository only. That keyring file is also what the cleanup step below removes by hand.

deb [signed-by=/etc/apt/keyrings/longsleep-golang-backports-noble.gpg] https://ppa.launchpadcontent.net/longsleep/golang-backports/ubuntu noble main

Check what apt now offers before you install anything, because the unversioned package and the newest release aren’t the same thing here.

apt-cache policy golang-go | grep -E "Candidate|launchpad"
apt-cache policy golang-1.27-go | grep -E "Candidate"

On our run golang-go from the PPA pointed at 1.26, a release behind, and the current Go was only available as the versioned golang-1.27-go package. Its version string carries a +jammy suffix even though it comes from the noble suite.

  Candidate: 2:1.26~0longsleep1
        500 https://ppa.launchpadcontent.net/longsleep/golang-backports/ubuntu noble/main amd64 Packages
  Candidate: 1.27.2-1longsleep1+jammy

So if you go this way, install the versioned package, not golang-go, or you’ll land one release behind without noticing. The PPA earns its place when you want Go updates to arrive with apt upgrade alongside everything else, and it costs you a third-party repository with its own signing key on the system. Install the versioned package and check where its binary went, because it doesn’t touch your PATH.

sudo apt-get install -y golang-1.27-go
command -v go || echo "no go on PATH"
ls /usr/lib/go-1.27/bin
/usr/lib/go-1.27/bin/go version

The install succeeded, yet go was not found. The package puts its binaries under /usr/lib/go-1.27/bin and, unlike golang-go, adds no /usr/bin/go symlink:

no go on PATH
go
gofmt
go version go1.27.2 linux/amd64

Put that directory at the front of your PATH for the current shell first. It goes at the front, not the end, so it wins over any /usr/bin/go left behind by the apt package. Testing it in one shell also means a typo can’t break your login before you know the line works:

export PATH=/usr/lib/go-1.27/bin:$PATH
go version
go env GOROOT GOTOOLCHAIN

Now go resolves to the PPA build, with GOROOT inside /usr/lib/go-1.27 and auto-download still on. When 1.28 lands in the PPA it will be a new package with a new directory, so the PATH line has to change with it.

go version go1.27.2 linux/amd64
/usr/lib/go-1.27
auto

To keep it for every login, including the tools go install puts in ~/go/bin, append the line to ~/.profile. We ran the export by hand in the lab, not this persisted form:

echo 'export PATH=/usr/lib/go-1.27/bin:$HOME/go/bin:$PATH' >> ~/.profile

To take the PPA route back out, remove the package first, then the repository and the keyring it added. Removing golang-1.27-go leaves its source package behind as an orphan, so run autoremove too:

sudo apt-get remove -y golang-1.27-go
sudo apt-get autoremove -y
sudo add-apt-repository -y --remove ppa:longsleep/golang-backports
sudo rm -f /etc/apt/keyrings/longsleep-golang-backports-noble.gpg
sudo apt-get update

The remove and autoremove steps took out both PPA packages (output trimmed to the removal lines):

Removing golang-1.27-go (1.27.2-1longsleep1+jammy) ...
Removing golang-1.27-src (1.27.2-1longsleep1+jammy) ...

After that, /etc/apt/sources.list.d/ held only official-package-repositories.list again and /usr/lib/go-1.27 no longer existed. The PPA left nothing else behind, so taking it out is clean.

Upgrade and remove Go

Upgrading a tarball install is the install again. The detection line picks up the new version, and the rm -rf before the extract clears the old tree, so the commands from the tarball section work unchanged for every future release. The same commands work on servers too, as our Go install for Rocky Linux and AlmaLinux shows.

GO_VER=$(curl -s "https://go.dev/VERSION?m=text" | head -1)
cd /tmp && curl -fsSLO "https://go.dev/dl/${GO_VER}.linux-amd64.tar.gz"
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf ${GO_VER}.linux-amd64.tar.gz

Run the checksum step between the download and the extract, as before. Your modules, the build cache and anything in ~/go/bin stay where they are. Tools built with go install keep running on the old compiler’s output until you reinstall them, which is harmless but worth doing after a major release.

Removing the apt version is a normal package removal, and you’ll want it gone before a tarball install so two different go binaries don’t compete on the PATH. The meta package and the versioned package both have to go, otherwise golang-1.22-go stays behind.

sudo apt-get remove -y golang-go golang-1.22-go
sudo apt-get autoremove -y
which go || echo "no go on PATH"

On our VM that left no go on the PATH, so nothing else had pulled Go in as a dependency. The ~/go directory from earlier tests stays, since apt never owned it.

no go on PATH

A tarball install leaves files in three places, and only the first two belong to the install itself:

  • /usr/local/go, the toolchain (283 MB here)
  • /etc/profile.d/go.sh, the PATH line
  • ~/go, the module cache, downloaded toolchains and installed tools

Clear the module cache while Go is still installed, because the cache files are read-only and a plain rm -rf fails on them. On our VM ~/go/pkg/mod held 386 MB, and rm -rf ~/go/pkg/mod stopped with permission errors like these:

rm: cannot remove '/home/josphat/go/pkg/mod/github.com/rakyll/[email protected]/hey_test.go': Permission denied
rm: cannot remove '/home/josphat/go/pkg/mod/github.com/rakyll/[email protected]/requester/now_other.go': Permission denied

go clean -modcache removed the whole directory. The build cache in ~/.cache/go-build is separate, and go clean -cache is the matching command for it (we didn’t time or size that one). Then remove the toolchain and the PATH file:

go clean -modcache
sudo rm -rf /usr/local/go
sudo rm -f /etc/profile.d/go.sh
bash -lc "command -v go || echo no go on PATH"

A fresh login shell no longer finds Go, because both the binary and the file that put it on the PATH are gone. Terminals that were already open still carry the old PATH entry, but it now points at a directory that doesn’t exist, so it does no harm:

no go on PATH

With the read-only cache gone, rm -rf ~/go as your normal user removes what is left (bin and an empty pkg in our run) without errors. Log out and back in so open sessions drop the old PATH too. If you are setting up Go for containers next, the Docker CE install on Linux Mint covers that.

Keep reading

Backup and Restore Linux Systems with Timeshift Debian Backup and Restore Linux Systems with Timeshift Ubuntu vs Linux Mint: Tested RAM, Boot Time and Snap Overhead Desktop Ubuntu vs Linux Mint: Tested RAM, Boot Time and Snap Overhead How To Install Wine on Linux Mint 22.3 / 22.2 / 22.1 Linux Mint How To Install Wine on Linux Mint 22.3 / 22.2 / 22.1 Best Monitor Arms for a Multi-Monitor Developer Desk Programming Best Monitor Arms for a Multi-Monitor Developer Desk Best Mouse and Keyboard for Programming Programming Best Mouse and Keyboard for Programming Best Go Programming Books for 2026: Beginner to Expert Books Best Go Programming Books for 2026: Beginner to Expert

Leave a Comment

Press ESC to close