Right, let’s get you set up with a working Go installation. This isn’t brain surgery, but there are a few ways to do it and a couple of potholes I’d like to steer you around. The goal here is to get a clean, maintainable, and standard installation. We’re not trying to impress anyone with our custom-built-from-source prowess. Yet.

The Official Installer: The Path of Least Resistance

For 99% of you, especially if you’re on Windows or macOS, the official installers from golang.org/dl are the way to go. They Just Work™. You download a file, click through an installer (or untar a archive), and you’re basically done. The crucial thing these installers do, which you might not appreciate until you’ve manually borked it, is they set up your entire workspace with the correct permissions and they put everything in the one true place Go expects it to be.

On Linux, you’ll typically get a .tar.gz archive. The installer’s “installation” process is just you, as a user, unpacking it into /usr/local. Don’t overthink it.

# Download the latest Linux AMD64 tarball (check the site for the exact name)
wget https://go.dev/dl/go1.21.4.linux-amd64.tar.gz

# Remove any previous old Go installation (safety first!)
sudo rm -rf /usr/local/go

# Extract the fresh tarball right into /usr/local
sudo tar -C /usr/local -xzf go1.21.4.linux-amd64.tar.gz

Why /usr/local? It’s the traditional place for locally installed software that isn’t managed by your system’s package manager (apt, yum, etc.). It keeps things clean and separate. The installer plops everything into /usr/local/go, so you can have multiple versions side-by-side by just renaming this directory if you’re feeling fancy (though there are better ways to manage that, which we’ll get to).

Now, the single most important post-install step: adding /usr/local/go/bin to your PATH. If you don’t do this, your shell will have no idea where to find the go command, and it will yell at you. This goes in your shell’s startup file, like ~/.bashrc, ~/.zshrc, or ~/.profile.

# Add this line to the end of your ~/.bashrc or ~/.zshrc
export PATH=$PATH:/usr/local/go/bin

Open a new terminal window and type go version. If it spits back a happy version number, you’ve won. Congratulations.

Package Managers: Convenience vs. Control

Here’s where things get… interesting. You can absolutely use your system’s package manager, like apt on Ubuntu (sudo apt install golang-go) or brew on macOS (brew install go). It’s tempting because it’s one line and it feels integrated. I’m not going to tell you it’s wrong, but I will tell you why I, and most seasoned Gophers, often avoid it.

The main issue is version lag. The repositories for these package managers are famously, almost impressively, slow to update. Go releases a new version every six months, like clockwork. Your OS’s stable repository might still be offering a version that’s two years old. You’ll miss out on critical performance improvements, new features, and security patches. It’s a bad trade-off for the minor convenience.

The other, more subtle, issue is that these packages often have… opinions. They might decide to split the standard library into different packages or install things in a non-standard location. This can lead to utterly confusing errors down the line when you’re trying to do something simple and the tooling can’t find what it’s looking for because it’s not where the entire Go ecosystem expects it to be.

So, my strong recommendation? Use the official installer. It’s the path the Go team explicitly designs for, and it guarantees you’re getting a vanilla, predictable, and up-to-date experience.

Verifying Your Installation

Don’t just trust the version command. Let’s make sure the whole toolchain actually works by doing what we came here to do: compile and run a tiny program. Create a new file, hello.go.

package main

import "fmt"

func main() {
    fmt.Println("Go is installed. The world is your oyster.")
}

Now, run it. The go run command is a beautiful thing: it compiles the code into a temporary executable and immediately runs it.

go run hello.go

If you see our profoundly optimistic message, you are officially in business. The compiler, linker, and runtime are all functioning correctly. You’ve successfully navigated the first, and arguably most boring, step. Now the fun can actually start.