Skip to content

Instantly share code, notes, and snippets.

@mlliarm
Last active October 27, 2025 06:59
Show Gist options
  • Save mlliarm/7feb67d19f89e9e2234c7faa2ffd2f88 to your computer and use it in GitHub Desktop.
Save mlliarm/7feb67d19f89e9e2234c7faa2ffd2f88 to your computer and use it in GitHub Desktop.
Download, verify and install locally the latest stable Go binary

Download, verify and install locally the latest stable Go binary

Dependencies

  • Virtualenv 20.13.0
  • Python 3.10.12+
  • beautifulsoup4 4.12.3
  • Tested on Ubuntu 22.04 LTS

Script

Let's call it dl-go.py.

import platform as pl
from bs4 import BeautifulSoup
import urllib.request as urlreq
import subprocess
import re

# Parse download page
page = urlreq.urlopen('https://go.dev/dl/')
soup = BeautifulSoup(page, features='html.parser')

# Get parent element of stable versions
stable_versions = soup.body.find('h2', attrs={'id':'stable'})

# Get next elements under the parent for stable versions
fnext = stable_versions.find_next()
y = fnext.find_all("tr", "")

# Get all stable versions
all_stable_versions = {}
for i in y:
    td_find = i.find("td", "filename")
    tt_find = i.find("tt")
    if td_find != None and tt_find != None:
        all_stable_versions[td_find.string] = tt_find.string

all_stable_versions_keys = list(all_stable_versions.keys())

# Getting the linux, mac and windows versions in a dict
stable_linux = {}
stable_mac = {}
stable_windows = {}

for key in all_stable_versions_keys:
    if "linux" in key:
        stable_linux[key] = all_stable_versions[key]
    elif "darwin" in key:
        stable_mac[key] = all_stable_versions[key]
    elif "windows" in key:
        stable_windows[key] = all_stable_versions[key]
    else:
        continue

# Get latest stable version
# https://stackoverflow.com/a/8955701
new_version = re.search('\d+(\.\d+){2,}',all_stable_versions_keys[0])
new_version = new_version.group(0)

# Get system and cpu info of host
# https://stackoverflow.com/a/7491509
plat = pl.platform().lower()
system = pl.system().lower()
cpu = pl.processor().lower()

if cpu == "x86_64":
    cpu = "amd64"

# Get current installed go version
try:
    installed_go = str(subprocess.run(['go', 'version'], check=True, text=True, capture_output=True).stdout)
except FileNotFoundError:
    installed_go = "0.0.1"
installed_go_version = re.search('\d+(\.\d+){2,}',installed_go)
installed_go_version = installed_go_version.group(0)
print("Installed go version is: {0}".format(installed_go_version))

# Get latest stable filename for current system
file_to_dl = "go" + new_version + "." + system + "-" + cpu + ".tar.gz"

# Get download url for file
download_url = "https://go.dev/dl/" + file_to_dl

# Download tar.gz file
if installed_go_version == new_version:
    print("Latest golang version installed.")
    print("Program will terminate now.")
    exit(0)
else:
    print("There's a new golang version !")
    print("Downloading {0}".format(file_to_dl))
    urlreq.urlretrieve(download_url, file_to_dl)

# Get SHA256 hashkey from scraped data for downloaded file
if "linux" in file_to_dl:
    hashkey = stable_linux[file_to_dl]
elif "darwin" in file_to_dl:
    hashkey = stable_mac[file_to_dl]
elif "windows" in file_to_dl:
    hashkey = stable_windows[file_to_dl]

# Get SHA256 hashkey from downloaded file
downloaded_hashkey = str(subprocess.run(['sha256sum', './{}'.format(file_to_dl)], 
                        check=True, text=True, capture_output=True).stdout) \
                    .split(" ")[0]

# Compare SHA256 hashkeys
# If not the same, exit script with an error message
if hashkey == downloaded_hashkey:
    print("Hashkey check: VALID")
else:
    print("ERROR: Hashkey check: INVALID !")
    print("Program will terminate now.")
    exit(0)

# Removing old version
# rm -rf /usr/local/go (as root)
if installed_go_version == "0.0.1":
    print("Golang not installed, skipping deletion")
else:
    print("Removing /usr/local/go")
    removed_output = str(subprocess.run(['rm', '-rf', '/usr/local/go'], check=True, text=True, capture_output=True).stdout)
    print(removed_output)

# Installing new version
# tar -C /usr/local -xzf ./go1.22.6.linux-amd64.tar.gz (as root)
print("Installing {0} to /usr/local".format(file_to_dl))
installed_output = str(subprocess.run(['tar', '-C','/usr/local/','-xzf','./{0}'.format(file_to_dl)],
            check=True, text=True, capture_output=True).stdout)
print(installed_output)

print("New version of golang is:")
go_version_output = str(subprocess.run(['go', 'version'], check=True, text=True, capture_output=True).stdout)
print(go_version_output)

Test

a) No golang installed

To test the above script build and run the following Dockerfile to test the scenario that you don't have golang installed:

FROM ubuntu:22.04
RUN apt-get update \
	&& apt-get install -y python3 python3-pip wget tar
ADD dl-go.py .
RUN pip3 install beautifulsoup4
RUN mkdir -p /usr/local/
ENV PATH="$PATH:/usr/local/go/bin"
CMD ["python3","./dl-go.py"]

Build:

docker build -t dl-go .

Run:

docker run dl-go

You should get as output:

$ docker run dl-go
Installed go version is: 0.0.1
There's a new golang version !
Downloading go1.23.0.linux-amd64.tar.gz
Hashkey check: VALID
Golang not installed, skipping deletion
Installing go1.23.0.linux-amd64.tar.gz to /usr/local

New version of golang is:
go version go1.23.0 linux/amd64

b) Golang installed (older version)

Use the following Dockerfile:

FROM ubuntu:22.04
RUN apt-get update \
	&& apt-get install -y python3 python3-pip wget tar

ADD dl-go.py .
RUN pip3 install beautifulsoup4
RUN mkdir -p /usr/local/ \
    && wget  https://go.dev/dl/go1.22.4.linux-amd64.tar.gz \
    && tar -C /usr/local/ -xzf ./go1.22.4.linux-amd64.tar.gz
ENV PATH="$PATH:/usr/local/go/bin"
CMD ["python3","./dl-go.py"]

Build and run as before.

You should get the following output:

Installed go version is: 1.22.4                                                                                                                                                                             
There's a new golang version !
Downloading go1.23.0.linux-amd64.tar.gz
Hashkey check: VALID
Removing /usr/local/go

Installing go1.23.0.linux-amd64.tar.gz to /usr/local

New version of golang is:
go version go1.23.0 linux/amd64

Resources

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment