Skip to content

Instantly share code, notes, and snippets.

@mdsohelmia
Last active January 22, 2026 09:00
Show Gist options
  • Select an option

  • Save mdsohelmia/fa42d8052f581a3d521a3a811b3f4ddd to your computer and use it in GitHub Desktop.

Select an option

Save mdsohelmia/fa42d8052f581a3d521a3a811b3f4ddd to your computer and use it in GitHub Desktop.
install-go
#!/usr/bin/env bash
set -euo pipefail
msg() { printf '%s\n' "$*"; }
warn() { printf '⚠️ %s\n' "$*" >&2; }
die() {
printf '❌ %s\n' "$*" >&2
exit 1
}
# -------- Colors --------
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# -------- Linux only --------
OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
[ "$OS" = "linux" ] || die "Linux only. Detected: $(uname -s)"
# -------- sudo/root handling --------
if command -v sudo >/dev/null 2>&1; then
SUDO="sudo"
else
SUDO=""
fi
if [ "$(id -u)" -ne 0 ] && [ -z "$SUDO" ]; then
die "Need root or sudo to auto-install missing commands and install Go to /usr/local."
fi
# -------- detect package manager --------
detect_pm() {
if command -v apt-get >/dev/null 2>&1; then
echo "apt"
return
fi
if command -v dnf >/dev/null 2>&1; then
echo "dnf"
return
fi
if command -v yum >/dev/null 2>&1; then
echo "yum"
return
fi
if command -v pacman >/dev/null 2>&1; then
echo "pacman"
return
fi
if command -v apk >/dev/null 2>&1; then
echo "apk"
return
fi
if command -v zypper >/dev/null 2>&1; then
echo "zypper"
return
fi
echo "unknown"
}
PM="$(detect_pm)"
[ "$PM" != "unknown" ] || die "No supported package manager found (apt/dnf/yum/pacman/apk/zypper). Install dependencies manually: curl tar awk"
install_pkgs() {
# shellcheck disable=SC2086
case "$PM" in
apt)
$SUDO apt-get update -y
$SUDO apt-get install -y "$@"
;;
dnf)
$SUDO dnf install -y "$@"
;;
yum)
$SUDO yum install -y "$@"
;;
pacman)
$SUDO pacman -Sy --noconfirm "$@"
;;
apk)
$SUDO apk add --no-cache "$@"
;;
zypper)
$SUDO zypper --non-interactive install "$@"
;;
esac
}
# Map command -> package name(s) per distro family
ensure_cmd() {
local cmd="$1"
if command -v "$cmd" >/dev/null 2>&1; then
return 0
fi
msg "πŸ”§ Missing '$cmd' β€” installing…"
case "$cmd" in
curl)
case "$PM" in
apt | dnf | yum | pacman | apk | zypper) install_pkgs curl ;;
esac
;;
tar)
case "$PM" in
apt | dnf | yum | pacman | apk | zypper) install_pkgs tar ;;
esac
;;
awk)
# awk is usually in gawk (or mawk) depending on distro
case "$PM" in
apt) install_pkgs gawk ;;
dnf | yum) install_pkgs gawk ;;
pacman) install_pkgs gawk ;;
apk) install_pkgs gawk ;;
zypper) install_pkgs gawk ;;
esac
;;
*)
die "Don't know how to install missing command: $cmd"
;;
esac
command -v "$cmd" >/dev/null 2>&1 || die "Failed to install '$cmd'. Please install it manually."
}
# -------- ensure prerequisites (auto-install) --------
ensure_cmd curl
ensure_cmd tar
ensure_cmd awk
# -------- architecture --------
M="$(uname -m)"
case "$M" in
x86_64 | amd64) ARCH="amd64" ;;
aarch64 | arm64) ARCH="arm64" ;;
i386 | i686) ARCH="386" ;;
*) die "Unsupported architecture: $M" ;;
esac
# -------- shell rc --------
detect_shell_rc() {
# Check current shell
case "$SHELL" in
*/zsh) echo "$HOME/.zshrc" ;;
*/fish) echo "$HOME/.config/fish/config.fish" ;;
*) echo "$HOME/.bashrc" ;;
esac
}
SHELL_RC="$(detect_shell_rc)"
INSTALL_DIR="/usr/local"
GO_BIN="$INSTALL_DIR/go/bin"
# -------- latest Go version --------
msg "πŸ” Fetching latest Go version..."
GO_VERSION_FULL="$(curl -fsSL 'https://go.dev/VERSION?m=text' | awk 'NR==1{print; exit}')"
[ -n "$GO_VERSION_FULL" ] || die "Could not determine latest Go version."
# -------- check if already installed --------
if [ -x "$GO_BIN/go" ]; then
CURRENT_VERSION="$("$GO_BIN/go" version 2>/dev/null | awk '{print $3}')" || CURRENT_VERSION=""
if [ "$CURRENT_VERSION" = "$GO_VERSION_FULL" ]; then
msg "βœ… Go $GO_VERSION_FULL is already installed and up to date"
"$GO_BIN/go" version
exit 0
fi
msg "πŸ”„ Upgrading from $CURRENT_VERSION to $GO_VERSION_FULL"
else
msg "πŸ“¦ Installing Go $GO_VERSION_FULL"
fi
GO_TAR="${GO_VERSION_FULL}.linux-${ARCH}.tar.gz"
URL="https://go.dev/dl/${GO_TAR}"
CHECKSUM_URL="https://go.dev/dl/?mode=json"
msg ""
msg "πŸ”Ή OS: linux"
msg "πŸ”Ή ARCH: $ARCH"
msg "πŸ”Ή Go: $GO_VERSION_FULL"
msg "πŸ”Ή URL: $URL"
msg "πŸ”Ή RC file: $SHELL_RC"
msg ""
# -------- download & install --------
TMPDIR="$(mktemp -d)"
trap 'rm -rf "$TMPDIR"' EXIT
cd "$TMPDIR"
msg "⬇️ Downloading Go..."
curl -fL --retry 3 --progress-bar -O "$URL"
# -------- checksum verification --------
msg "πŸ” Verifying checksum..."
EXPECTED_SHA256="$(curl -fsSL "$CHECKSUM_URL" |
awk -v fname="$GO_TAR" '
BEGIN { RS="[{},]"; FS=":" }
/"filename"/ { gsub(/[" ]/, "", $2); file=$2 }
/"sha256"/ { gsub(/[" ]/, "", $2); sha=$2 }
file == fname && sha { print sha; exit }
')"
if [ -n "$EXPECTED_SHA256" ]; then
ACTUAL_SHA256="$(sha256sum "$GO_TAR" | awk '{print $1}')"
if [ "$EXPECTED_SHA256" = "$ACTUAL_SHA256" ]; then
msg "βœ… Checksum verified"
else
die "Checksum mismatch! Expected: $EXPECTED_SHA256, Got: $ACTUAL_SHA256"
fi
else
warn "Could not fetch checksum, skipping verification"
fi
# -------- verify archive --------
msg "πŸ“‚ Verifying archive..."
tar -tzf "$GO_TAR" >/dev/null || die "Archive verification failed"
# -------- install --------
msg "πŸ“₯ Installing to $INSTALL_DIR..."
$SUDO rm -rf "$INSTALL_DIR/go"
$SUDO tar -C "$INSTALL_DIR" -xzf "$GO_TAR"
# -------- PATH and environment update (idempotent) --------
msg "πŸ”§ Configuring environment..."
setup_shell_env() {
local rc_file="$1"
local is_fish=false
[[ "$rc_file" == *"fish"* ]] && is_fish=true
touch "$rc_file"
if [ "$is_fish" = true ]; then
# Fish shell syntax
local go_path_entry="set -gx PATH $GO_BIN \$PATH"
local gopath_entry='set -gx GOPATH $HOME/go'
local gobin_entry='set -gx PATH $GOPATH/bin $PATH'
if ! grep -q "set -gx PATH $GO_BIN" "$rc_file" 2>/dev/null; then
printf '\n# Go installation\n%s\n%s\n%s\n' "$go_path_entry" "$gopath_entry" "$gobin_entry" >>"$rc_file"
msg "βœ… Environment updated in $rc_file"
else
msg "πŸ”Ή Environment already configured in $rc_file"
fi
else
# Bash/Zsh syntax
local go_path_entry="export PATH=\"${GO_BIN}:\$PATH\""
local gopath_entry='export GOPATH="$HOME/go"'
local gobin_entry='export PATH="$GOPATH/bin:$PATH"'
if ! grep -q "export PATH=\"${GO_BIN}" "$rc_file" 2>/dev/null; then
printf '\n# Go installation\n%s\n%s\n%s\n' "$go_path_entry" "$gopath_entry" "$gobin_entry" >>"$rc_file"
msg "βœ… Environment updated in $rc_file"
else
msg "πŸ”Ή Environment already configured in $rc_file"
fi
fi
}
setup_shell_env "$SHELL_RC"
# -------- create GOPATH directory --------
mkdir -p "$HOME/go/bin" "$HOME/go/src" "$HOME/go/pkg"
# -------- verify installation --------
msg ""
msg "=================================================="
msg " Go Installation Complete"
msg "=================================================="
msg ""
"$GO_BIN/go" version
msg ""
msg "πŸ“ Go binary: $GO_BIN/go"
msg "πŸ“ GOPATH: \$HOME/go"
msg "πŸ“ Shell RC: $SHELL_RC"
msg ""
msg "ℹ️ Restart your shell or run:"
msg " source \"$SHELL_RC\""
msg ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment