Debian’s default Go package is stable, but it falls behind upstream quickly when projects need newer language features or toolchain fixes. If you need to install Go on Debian, often searched as Golang, the best method depends on whether you want Debian-managed updates or the current upstream release.
Default Debian package sources currently ship Go 1.24.x on Debian 13, Go 1.19.x on Debian 12, and Go 1.15.x on Debian 11. You can stay with the Debian APT package for the distro-managed route, or switch to the official tarball from go.dev when you need the current upstream stable branch. Source builds remain useful when you need to patch or inspect the Go toolchain itself.
Install Go on Debian
Three installation paths are available on Debian. APT is the easiest to maintain, the official tarball tracks the latest stable Go release, and source builds are mainly useful when you need to patch or inspect the toolchain itself.
| Method | Channel | Current Branch | Update Behavior | Best For |
|---|---|---|---|---|
| APT | Debian repositories | Debian 13: 1.24.x, Debian 12: 1.19.x, Debian 11: 1.15.x | Updates through APT | Stable systems that prefer distro-managed packages |
| Official tarball | go.dev downloads | Latest stable upstream branch | Manual reinstall with checksum verification | Developers who need a newer upstream toolchain |
| Source build | Go source tree | Latest stable or chosen tag | Manual rebuild | Contributors and users patching Go itself |
If you want the shortest route to a decision, use this quick pick before you move into the install steps.
- APT for stability: Stick with Debian’s package when Debian 13’s Go 1.24.x, Debian 12’s Go 1.19.x, or Debian 11’s Go 1.15.x is already new enough for your projects.
- Official tarball for the latest release: Use the upstream archive when you want the current stable toolchain and do not mind reinstalling it with checksum verification during upgrades.
- Source build for toolchain work: Keep this path for patching Go, inspecting the source tree, or testing a specific upstream release tag.
Update Debian and install Go prerequisites
Refresh package metadata first so each install method starts from a current Debian system.
sudo apt update && sudo apt upgrade
These commands use
sudofor root privileges. If your account does not have sudo access yet, follow how to add a user to sudoers on Debian.
Install the tools used by the tarball and source methods first. Desktop systems often already have some of them, but server and minimal installs usually do not. The jq package parses Go’s JSON release metadata so the download commands do not depend on fragile HTML scraping.
sudo apt install ca-certificates curl jq tar
Install Go from Debian APT on Debian
The Debian package is the lowest-maintenance option because APT keeps it updated with the rest of your system. The package name is golang-go, but the command it installs is still go.
sudo apt install golang-go
Verify which Go release Debian installed. Debian 13 currently uses the Go 1.24 branch from golang-1.24-go, while Debian 12 and Debian 11 use older packaged branches.
go version
go version go1.24.4 linux/amd64
APT users do not need extra PATH configuration because Debian already exposes the
gobinary through/usr/bin/go.
Install Go from the official tarball on Debian
The official tarball is the better choice when you need the latest stable release from upstream instead of Debian’s older packaged branch.
Check your Debian architecture first so the download command picks the right Go archive. The mapping handles Debian’s package architecture names against the filenames published on go.dev, then stops with a clear error for architectures that need manual selection.
dpkg --print-architecture
amd64
Download the latest stable Go tarball from the JSON metadata endpoint. The command selects the Linux archive for your Debian architecture, downloads it to /tmp, and verifies the SHA256 checksum published by Go before you extract it.
case "$(dpkg --print-architecture)" in
amd64) GO_ARCH=amd64 ;;
arm64) GO_ARCH=arm64 ;;
i386) GO_ARCH=386 ;;
*) GO_ARCH="" ;;
esac
if [ -z "$GO_ARCH" ]; then
echo "Choose the correct tarball manually from https://go.dev/dl/ for this Debian architecture."
else
GO_METADATA=$(curl -fsSL 'https://go.dev/dl/?mode=json')
GO_TARBALL=$(GOOS=linux GOARCH="$GO_ARCH" jq -r '.[0].files[] | select(.os == env.GOOS and .arch == env.GOARCH and .kind == "archive") | .filename' <<<"$GO_METADATA")
GO_SHA256=$(GOOS=linux GOARCH="$GO_ARCH" jq -r '.[0].files[] | select(.os == env.GOOS and .arch == env.GOARCH and .kind == "archive") | .sha256' <<<"$GO_METADATA")
if [ -z "$GO_TARBALL" ] || [ "$GO_TARBALL" = null ] || [ -z "$GO_SHA256" ] || [ "$GO_SHA256" = null ]; then
echo "No Go Linux archive was found for $GO_ARCH. Choose the correct tarball manually from https://go.dev/dl/."
else
curl -fL --progress-bar -o "/tmp/${GO_TARBALL}" "https://go.dev/dl/${GO_TARBALL}"
printf '%s %s\n' "$GO_SHA256" "/tmp/${GO_TARBALL}" | sha256sum -c -
echo "$GO_TARBALL"
fi
fi
Relevant output ends with the checksum status and the selected archive filename.
/tmp/go1.26.3.linux-amd64.tar.gz: OK go1.26.3.linux-amd64.tar.gz
Continue only when the checksum line reports OK and a filename appears. If the block prints an architecture or metadata error instead, choose the correct archive from the Go downloads page before extracting anything.
Run the extraction commands in the same terminal session so $GO_TARBALL still points to the file you just downloaded.
Removing
/usr/local/godeletes the existing upstream tarball toolchain. Do this before extracting the new release so files from two Go versions do not mix, but do not store projects or custom files inside that directory.
if [ -d /usr/local/go ]; then
sudo rm -rf /usr/local/go
fi
Extract the new toolchain into /usr/local and remove the downloaded archive after the install finishes.
sudo tar -C /usr/local -xzf "/tmp/${GO_TARBALL}"
rm -f "/tmp/${GO_TARBALL}"
Confirm the tarball install is in place before you add it to your PATH.
/usr/local/go/bin/go version
go version go1.26.3 linux/amd64
Build Go from source on Debian
A source build is mainly for people who want to patch Go or work directly from the upstream tree. Current Go releases need a recent bootstrap compiler, so the simplest path is to complete the official tarball method first and then reuse /usr/local/go as GOROOT_BOOTSTRAP.
Keep the source tree under your home directory instead of /tmp. That matches upstream guidance more closely, avoids cleanup races, and gives the build a normal writable tree that persists across shells.
Source builds also need Git for the upstream checkout and GCC for cgo-enabled packages. The earlier prerequisite step already installed jq for release metadata parsing.
sudo apt install git gcc
The next command removes any existing
$HOME/goroot-srccheckout before cloning a fresh release tag. Commit, stash, or move local Go source changes before running it.
GO_VERSION=$(curl -fsSL 'https://go.dev/dl/?mode=json' | jq -r '.[0].version')
if [ -z "$GO_VERSION" ] || [ "$GO_VERSION" = null ]; then
echo "Error: could not detect the latest Go release from go.dev."
else
rm -rf "$HOME/goroot-src"
git clone --depth 1 --branch "$GO_VERSION" https://go.googlesource.com/go "$HOME/goroot-src"
fi
Verify that the source tree is on the release tag you expect before you start the build.
git -C "$HOME/goroot-src" describe --tags --exact-match
go1.26.3
Build Go from the source tree by pointing GOROOT_BOOTSTRAP at the tarball install you already placed in /usr/local/go.
export GOROOT_BOOTSTRAP=/usr/local/go
cd "$HOME/goroot-src/src" && ./make.bash
The final build lines include your actual home directory. For a user named username, the success output ends like this.
Installed Go for linux/amd64 in /home/username/goroot-src Installed commands in /home/username/goroot-src/bin *** You need to add /home/username/goroot-src/bin to your PATH. ***
Check the resulting binary from the source tree before you use it in your shell profile.
"$HOME/goroot-src/bin/go" version
go version go1.26.3 linux/amd64
Configure Go on Debian
APT installs do not need extra PATH work, but tarball and source builds do. Most users also do not need to set GOPATH manually anymore because Go defaults to $HOME/go; adding $HOME/go/bin to your PATH is usually enough for tools installed with go install.
Add a tarball install to PATH on Debian
Use this profile entry when you installed Go under /usr/local/go. The export line updates the current shell, while the ~/.profile entry persists for new terminal sessions.
touch "$HOME/.profile"
grep -qxF 'export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin' "$HOME/.profile" || printf '\n# Go toolchain\nexport PATH=$PATH:/usr/local/go/bin:$HOME/go/bin\n' >> "$HOME/.profile"
export PATH="$PATH:/usr/local/go/bin:$HOME/go/bin"
Add a source build to PATH on Debian
Use this profile entry instead when you built Go in $HOME/goroot-src. Open a new terminal after this step when you want the profile entry to load automatically.
touch "$HOME/.profile"
grep -qxF 'export PATH=$PATH:$HOME/goroot-src/bin:$HOME/go/bin' "$HOME/.profile" || printf '\n# Go source build\nexport PATH=$PATH:$HOME/goroot-src/bin:$HOME/go/bin\n' >> "$HOME/.profile"
export PATH="$PATH:$HOME/goroot-src/bin:$HOME/go/bin"
Verify the active Go binary on Debian
Check which binary your shell resolves first so you know whether APT, the tarball, or the source tree is active.
command -v go
go version
| Resolved Path | Likely Install Method |
|---|---|
/usr/bin/go | Debian APT package |
/usr/local/go/bin/go | Official upstream tarball |
$HOME/goroot-src/bin/go | Source build from your home directory |
Verify Go on Debian with a test program
Build one small module before you move on to real work. That confirms the compiler, module support, and runtime are all working with the active Go binary on your PATH.
Create a test directory and initialize a module.
mkdir -p "$HOME/go-hello" && cd "$HOME/go-hello" && go mod init hello
go: creating new go.mod: module hello
Write a short program with printf so you can paste it directly without dealing with a heredoc.
printf '%s\n' 'package main' '' 'import "fmt"' '' 'func main() {' ' fmt.Println("Hello, World!")' '}' > hello.go
Run the program with the Go binary that is currently active in your shell.
go run hello.go
Hello, World!
Remove the test directory when you are done with it.
cd "$HOME" && rm -rf "$HOME/go-hello"
Update Go on Debian
The update command depends on how you installed Go in the first place.
- APT users should keep the Debian package on the APT track.
- Tarball users should re-download the latest archive from
go.dev. - Source-build users should keep a reusable update script with the source tree so future upgrades stay repeatable.
Update the Debian APT package on Debian
Use APT’s single-package upgrade mode when you want Debian to update only the packaged Go toolchain.
sudo apt update && sudo apt install --only-upgrade golang-go
Confirm the package version after the upgrade finishes.
go version
go version go1.24.4 linux/amd64
Update the official tarball install on Debian
Tarball installs update outside APT, so a small helper keeps release lookup, checksum verification, extraction, and cleanup repeatable. Create it after the tarball method is already installed under /usr/local/go.
The update removes the existing
/usr/local/gotree before extracting the replacement. Keep projects, custom scripts, and module workspaces outside that directory.
cat > "$HOME/update-go-tarball.sh" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
INSTALL_ROOT="/usr/local/go"
if [ "$(id -u)" -eq 0 ]; then
echo "Run this script as a regular user so downloads stay in a user-owned temporary directory."
exit 1
fi
for cmd in awk curl dpkg jq sha256sum sudo tar; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "Error: $cmd is required but not installed."
exit 1
fi
done
if [ ! -x "$INSTALL_ROOT/bin/go" ]; then
echo "Error: $INSTALL_ROOT/bin/go was not found."
echo "Install Go from the official tarball first before using this updater."
exit 1
fi
case "$(dpkg --print-architecture)" in
amd64) GO_ARCH=amd64 ;;
arm64) GO_ARCH=arm64 ;;
i386) GO_ARCH=386 ;;
*)
echo "Choose the correct tarball manually from https://go.dev/dl/ for this Debian architecture."
exit 1
;;
esac
GO_METADATA=$(curl -fsSL 'https://go.dev/dl/?mode=json')
LATEST_VERSION=$(jq -r '.[0].version' <<<"$GO_METADATA")
GO_TARBALL=$(GOOS=linux GOARCH="$GO_ARCH" jq -r '.[0].files[] | select(.os == env.GOOS and .arch == env.GOARCH and .kind == "archive") | .filename' <<<"$GO_METADATA")
GO_SHA256=$(GOOS=linux GOARCH="$GO_ARCH" jq -r '.[0].files[] | select(.os == env.GOOS and .arch == env.GOARCH and .kind == "archive") | .sha256' <<<"$GO_METADATA")
if [ -z "$LATEST_VERSION" ] || [ "$LATEST_VERSION" = null ] || [ -z "$GO_TARBALL" ] || [ "$GO_TARBALL" = null ] || [ -z "$GO_SHA256" ] || [ "$GO_SHA256" = null ]; then
echo "Error: could not resolve the latest Go Linux archive for $GO_ARCH."
exit 1
fi
CURRENT_VERSION=$("$INSTALL_ROOT/bin/go" version | awk '{print $3}')
echo "Current tarball version: $CURRENT_VERSION"
echo "Latest upstream version: $LATEST_VERSION"
if [ "$CURRENT_VERSION" = "$LATEST_VERSION" ]; then
echo "Go tarball install is already up to date."
exit 0
fi
TMP_DIR=$(mktemp -d)
trap 'rm -rf "$TMP_DIR"' EXIT
ARCHIVE_PATH="$TMP_DIR/$GO_TARBALL"
curl -fL --progress-bar -o "$ARCHIVE_PATH" "https://go.dev/dl/${GO_TARBALL}"
printf '%s %s\n' "$GO_SHA256" "$ARCHIVE_PATH" | sha256sum -c -
sudo rm -rf "$INSTALL_ROOT"
sudo tar -C /usr/local -xzf "$ARCHIVE_PATH"
"$INSTALL_ROOT/bin/go" version
echo "Go tarball install updated to $LATEST_VERSION."
EOF
Make the helper executable and keep it in your home directory so it is easy to inspect before each manual update.
chmod +x "$HOME/update-go-tarball.sh"
Run the helper when you want to check for a newer upstream stable release.
~/update-go-tarball.sh
Current tarball version: go1.26.3 Latest upstream version: go1.26.3 Go tarball install is already up to date.
Source builds follow the same release cadence as the tarball, but they deserve their own update path because the tree stays under your home directory and does not update through APT.
Create a Go source update script on Debian
Source builds are easier to maintain when you keep one reusable script next to the source tree. This version checks for required tools, confirms the source tree and bootstrap compiler exist, skips the rebuild when you are already current, and then fetches only the latest stable tag before building.
cat > "$HOME/update-go-source.sh" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
SOURCE_DIR="$HOME/goroot-src"
BOOTSTRAP_ROOT="/usr/local/go"
LOG_FILE="$HOME/goroot-src-update.log"
if [ "$(id -u)" -eq 0 ]; then
echo "Run this script as a regular user. The source build in $HOME should stay owned by your user."
exit 1
fi
for cmd in curl git jq; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "Error: $cmd is required but not installed."
exit 1
fi
done
if [ ! -d "$SOURCE_DIR/.git" ]; then
echo "Error: $SOURCE_DIR does not contain the Go source tree."
echo "Build Go from source first so this script has a checkout to update."
exit 1
fi
if [ ! -x "$BOOTSTRAP_ROOT/bin/go" ]; then
echo "Error: $BOOTSTRAP_ROOT/bin/go was not found."
echo "Install or reinstall the official Go tarball first so GOROOT_BOOTSTRAP is available."
exit 1
fi
if [ -n "$(git -C "$SOURCE_DIR" status --porcelain)" ]; then
echo "Error: $SOURCE_DIR has uncommitted changes."
echo "Commit, stash, or discard them before running the update script."
exit 1
fi
LATEST_TAG=$(curl -fsSL 'https://go.dev/dl/?mode=json' | jq -r '.[0].version')
if [ -z "$LATEST_TAG" ] || [ "$LATEST_TAG" = null ]; then
echo "Error: Could not detect the latest Go release from go.dev."
exit 1
fi
CURRENT_TAG=$(git -C "$SOURCE_DIR" describe --tags --exact-match 2>/dev/null || echo none)
echo "Current tag: $CURRENT_TAG"
echo "Latest tag: $LATEST_TAG"
if [ "$CURRENT_TAG" = "$LATEST_TAG" ]; then
echo "Go source build is already up to date."
exit 0
fi
echo "Fetching $LATEST_TAG..."
git -C "$SOURCE_DIR" fetch --depth 1 origin "refs/tags/$LATEST_TAG:refs/tags/$LATEST_TAG"
echo "Checking out $LATEST_TAG..."
git -C "$SOURCE_DIR" checkout "$LATEST_TAG"
echo "Building Go from source..."
export GOROOT_BOOTSTRAP="$BOOTSTRAP_ROOT"
cd "$SOURCE_DIR/src"
./make.bash | tee "$LOG_FILE"
echo "Verifying the updated source build..."
"$SOURCE_DIR/bin/go" version
echo "Go source build updated to $LATEST_TAG."
EOF
Make the script executable before you try to run it. The script also writes its build output to $HOME/goroot-src-update.log, which gives you one place to review failures later.
chmod +x "$HOME/update-go-source.sh"
Run the update script manually whenever you want to rebuild the source tree against the latest stable Go tag.
~/update-go-source.sh
Current tag: go1.26.3 Latest tag: go1.26.3 Go source build is already up to date.
When the script finds a newer release, verify the resulting source-built binary from the checkout itself.
"$HOME/goroot-src/bin/go" version
go version go1.26.3 linux/amd64
Avoid running this script from cron. Source builds can fail because of network issues, toolchain regressions, or local dependency problems, so run it manually and review the output before replacing the toolchain you rely on.
Troubleshoot Go on Debian
Most Go problems on Debian come from PATH mismatches, mixed installation methods, or missing build tools.
Fix go command not found on Debian
Start by checking whether your shell can resolve the go binary at all.
command -v go || echo 'go not found'
go not found
If you installed Go from Debian packages, confirm the package is still present.
dpkg-query -W -f='${Status} ${Version}\n' golang-go 2>/dev/null
On Debian 13, an installed package reports the current metapackage version. Debian 12 and Debian 11 show older metapackage versions from their own repositories.
install ok installed 2:1.24~2
If you installed the tarball or a source build, check the binaries those methods create.
ls /usr/local/go/bin/go "$HOME/goroot-src/bin/go" 2>/dev/null
A source build shows your actual home path. For a user named username, the paths look like this.
/usr/local/go/bin/go /home/username/goroot-src/bin/go
When the binary exists but the shell still cannot find it, load the profile entry created earlier and clear Bash’s command cache before checking the resolved path again. Opening a new terminal accomplishes the same thing for future sessions.
. "$HOME/.profile"
hash -r
command -v go
/usr/local/go/bin/go
Fix mixed APT and tarball Go versions on Debian
Two Go installs usually show up as multiple paths in which -a go. That leaves your shell using whichever path appears first.
which -a go
/usr/local/go/bin/go /usr/bin/go
If you want to keep the newer tarball release, remove the Debian package so the older binary stops competing for your PATH.
sudo apt purge golang-go golang-src
sudo apt autoremove
If you want to go back to Debian’s packaged toolchain instead, remove the tarball directory and drop its PATH line from ~/.profile. Open a new terminal after editing the profile so the old path is not reused.
Removing
/usr/local/godeletes the upstream tarball install. Do not run this cleanup if another manually installed Go toolchain still uses that directory.
if [ -d /usr/local/go ]; then
sudo rm -rf /usr/local/go
fi
touch "$HOME/.profile"
sed -i '\|/usr/local/go/bin|d' "$HOME/.profile"
hash -r
Fix gcc missing during Go builds on Debian
Go itself can build without C code in some cases, but many Go projects and cgo-dependent tools still need gcc available.
sudo apt install gcc
gcc --version | head -n 1
gcc (Debian 14.2.0-19) 14.2.0
Remove Go from Debian
Remove the Go method you actually installed. APT, tarball, and source builds clean up differently.
Remove the Debian APT package on Debian
Purge the Debian package and then let APT show any dependencies that are no longer needed. Review the autoremove transaction before accepting it, especially on systems where other development packages were installed separately.
sudo apt update
sudo apt purge golang-go golang-src
sudo apt autoremove
Verify that Debian no longer sees the APT Go packages as installed.
dpkg-query -W -f='${db:Status-Abbrev} ${binary:Package}\n' golang-go golang-src 2>/dev/null | grep '^ii' || echo 'Go APT packages removed'
Go APT packages removed
If package names still appear with an ii status, repeat the purge step and check whether another package depends on them.
Remove tarball or source Go installs on Debian
Tarball installs live in /usr/local/go, and source builds typically live in $HOME/goroot-src.
The cleanup removes the upstream tarball tree, the source checkout, helper scripts, build logs, the test directory, and Go workspace/cache directories. The
$HOME/goworkspace can contain downloaded modules, compiled binaries, and tools you installed withgo install, so remove any path you want to keep before running the deletion command.
Review the paths that exist before deleting custom Go files.
ls -d /usr/local/go "$HOME/goroot-src" "$HOME/go" "$HOME/.cache/go-build" "$HOME/go-hello" "$HOME/update-go-tarball.sh" "$HOME/update-go-source.sh" "$HOME/goroot-src-update.log" 2>/dev/null
if [ -d /usr/local/go ]; then
sudo rm -rf /usr/local/go
fi
rm -rf "$HOME/goroot-src" "$HOME/go" "$HOME/.cache/go-build" "$HOME/go-hello" "$HOME/update-go-tarball.sh" "$HOME/update-go-source.sh" "$HOME/goroot-src-update.log"
Remove the PATH entries from your shell profile so a new terminal does not keep pointing at a deleted Go binary.
touch "$HOME/.profile"
sed -i '\|/usr/local/go/bin|d;\|/goroot-src/bin|d' "$HOME/.profile"
hash -r
Use a path-specific check here so Debian’s packaged /usr/bin/go can stay installed without making the cleanup look incomplete.
found=0
for path in /usr/local/go/bin/go "$HOME/goroot-src/bin/go"; do
if [ -e "$path" ]; then
echo "Still present: $path"
found=1
fi
done
if [ "$found" -eq 0 ]; then
echo 'custom Go binaries removed'
fi
custom Go binaries removed
Conclusion
Go is installed on Debian with a verified toolchain, a working test module, and a clear update path whether you kept APT or moved to the upstream release. If your next step is real project work, pair it with Install Git on Debian for version control and Install Docker on Debian when you want to test containerized builds.


Why should we run sudo apt update && sudo apt upgrade if we didn’t use it?
Good question, R. Rahwana. Running
sudo apt update && sudo apt upgradebefore installing new software ensures your package lists are current and existing packages have the latest security patches. This prevents dependency conflicts and ensures tools likecurl,jq, andtarare available for the Go tarball workflow.It is technically optional if your system is already up to date, but including it in setup steps helps readers starting from minimal or freshly installed systems avoid unexpected issues.