How to Install Go on Ubuntu and Debian Linux

Install Go on Ubuntu or Debian by downloading the binary, extracting it to /usr/local, and updating your PATH environment variable.

The command not found wall

You open your terminal, type go version, and the shell replies with bash: go: command not found. You've followed a tutorial that assumes Go is already there, or you just downloaded a file and the system still doesn't know where to look. This is the first hurdle for every Go developer on Linux. The language isn't pre-installed on Ubuntu or Debian, and the shell needs explicit instructions to locate the tools.

Installing Go follows a Unix tradition that keeps your system clean and your toolchain reliable. You fetch a compressed archive from the official source, unpack it into a standard system directory, and update your environment so the shell can find the executables. This process avoids package managers because the official Go team releases binaries that are tested against the toolchain itself. Package repositories often lag behind, and Go's tooling expects a specific directory structure.

Think of the installation like setting up a professional workshop. The archive is a crate of precision tools. You unpack the crate into a dedicated cabinet at /usr/local. Then you give your apprentice, the shell, a map that points to the cabinet. Without the map, the apprentice doesn't know where to look when you ask for a wrench. The PATH variable is that map.

The standard installation sequence

Here's the standard installation sequence: download the official archive, extract it to the system directory, and update your shell configuration.

# Download the official Go archive for Linux AMD64
wget https://go.dev/dl/go1.22.0.linux-amd64.tar.gz

# Extract to /usr/local so the binary lands in /usr/local/go/bin
sudo tar -C /usr/local -xzf go1.22.0.linux-amd64.tar.gz

# Append the Go binary path to the shell's PATH variable
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc

# Reload the shell configuration to apply changes immediately
source ~/.bashrc

The wget command fetches the archive from the Go distribution server. The tar command extracts the contents. The -C flag is critical: it tells tar to change to /usr/local before extracting. If you omit -C, the files scatter across your current directory, creating a mess of nested folders. The sudo prefix grants permission to write to /usr/local, which is owned by root. The echo command appends the path export to your shell's configuration file. The source command reloads the configuration so the current session recognizes the new path.

If you skip sudo, the extraction fails with tar: /usr/local/go/bin/go: Cannot open: Permission denied. The directory is protected, and only the superuser can write to it.

The Go community convention is to install the binary at /usr/local/go. The official documentation assumes this path. Deviating from it requires manual configuration of the GOROOT environment variable, which causes more problems than it solves. Trust the convention. Let the toolchain find itself.

Architecture and download URLs

The download URL contains clues about your system. The filename go1.22.0.linux-amd64.tar.gz breaks down into three parts. linux is the operating system. amd64 is the CPU architecture, also known as x86_64. tar.gz is the compression format.

If you are running Ubuntu on a Raspberry Pi, a modern ARM server, or a cloud instance that uses ARM, the amd64 binary will not work. You need the arm64 variant. Check your architecture with uname -m. If the output is x86_64, use amd64. If the output is aarch64, use arm64.

If you run an amd64 binary on an arm64 system, the kernel rejects it immediately with bash: ./go: Exec format error. The binary is compiled for a different instruction set, and the processor cannot execute it.

Verifying the environment

Verify the installation works and inspect the environment variables to ensure everything is configured correctly.

# Check the installed version to confirm the binary is accessible
go version

# Display all Go environment variables to verify configuration
go env

# Filter for the workspace path to confirm the default location
go env GOPATH

The go version command prints the version number, operating system, and architecture. If this command runs, the binary is in your PATH and the installation succeeded. The go env command dumps all environment variables that the Go toolchain uses. This is the diagnostic tool you reach for when things break. It shows the compiler's view of the world.

Go 1.11 introduced modules, which changed how dependencies work. The GOPATH variable still exists, but you rarely need to set it manually. The toolchain defaults to $HOME/go if GOPATH is unset. Your source code lives in your editor, and modules handle dependencies automatically. You only care about GOPATH when you run go install to build executables, which land in $GOPATH/bin.

If you manually set GOPATH to a weird location, the toolchain might struggle to find cached modules. Leave GOPATH alone unless you have a specific reason to move it. The default works for 99% of developers.

Shell persistence and alternatives

The ~/.bashrc file configures the Bash shell. If you use Zsh, which is the default on some newer Ubuntu setups or if you switched manually, you need to update ~/.zshrc instead. The syntax is identical.

# If you use zsh, update the profile file instead of bashrc
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.zshrc

# Reload the zsh configuration
source ~/.zshrc

Some users prefer to put the PATH export in ~/.profile or ~/.bash_profile. These files run for login shells, while ~/.bashrc runs for interactive non-login shells. On Ubuntu, ~/.bashrc is sourced by ~/.profile, so putting the export in ~/.bashrc covers most cases. If you open a new terminal and go version still fails, check which shell is running with echo $SHELL and ensure you edited the right file.

If you forget to capture the path in your shell config, the go command disappears when you open a new terminal. The source command only affects the current session. The file update persists across reboots.

Pitfalls and common errors

The apt package manager offers a golang package, but it often lags behind the current release. Ubuntu 22.04 might ship Go 1.18 while the latest stable version is 1.22. If you install via apt, you get an older compiler that rejects newer syntax.

The compiler rejects programs that use features introduced after the installed version. You might see errors like undefined: slices.Contains if you try to use the slices package added in Go 1.21 on a system running Go 1.18. The package exists in the standard library, but your compiler doesn't know about it.

Mixing apt installations with the official binary causes confusion. The apt package might install Go to /usr/lib/go, while the binary lives in /usr/local/go. If your PATH points to the wrong location, you get inconsistent behavior. Stick to one method. The official binary is the recommended path.

Another pitfall is setting GOROOT manually. The GOROOT variable points to the directory where Go is installed. The toolchain sets this automatically based on where the go binary resides. If you set GOROOT to the wrong path, the compiler cannot find standard library packages.

The compiler aborts with import "fmt": cannot find module providing package if GOROOT is misconfigured. The standard library is part of the Go distribution, and the compiler looks for it relative to GOROOT. A broken GOROOT breaks everything. Delete any manual GOROOT exports from your shell config. Let the toolchain manage it.

Goroutine leaks are not an installation issue, but they are the first bug you'll encounter once you start coding. The installation gets the toolchain running. The code you write determines whether programs finish or hang. The toolchain is just the foundation.

Decision matrix

Use the official binary from go.dev when you want the latest stable release and full compatibility with the Go toolchain.

Use the apt package manager when you are on a restricted system where downloading external binaries is forbidden, accepting that the version may lag behind the current release.

Use snap or flatpak when you need sandboxed isolation for experiments, though these formats can interfere with file system access patterns that Go modules expect.

Use the source build when you need to debug the Go compiler itself or require a patch that hasn't been released yet.

The official binary wins. Package managers lag. Check go env before you guess.

Where to go next