A Better way to install Golang (Go) on Raspberry Pi

I recently want to install Golang(Go) on my Raspberry Pi, and realised that the easy way to install Golang may not be the better way to install Golang on Rasperry Pi.

If you search the internet you are likely see some of the old tutorials for installing some very old version of Golang from some third-party repo or cross-compiling it by yourself, some of it dated back to the early release of Rasperry Pi, that’s very long ago in software evolution, don’t follow those instructions. When I search on internet, I always looks at the date of the instruction/article, and if it is a few years old or without the date of when the instruction is published, I will generally ignore the instruction and look for more recent information.

The Easy Way

If you search “Golang Raspberry Pi”, you are likely come across this link “Install Golang the easy way” on Raspberry Pi Stack Exchange.
Golang is included in Debian (and therefore Raspbian) linux distribution, so the easy way to install Golang is using the simple and familiar linux command:

sudo apt-get install golang

However, a quick look at Raspbian Stretch package (as at the writing of this article, my installation is based on 2019-04-08-raspbian-stretch-lite.img image), the current Golang version that is packaged with the Raspbian is v1.8, and this can be confirmed by running command sudo apt-cache search golang|grep golang-1.*:

hcheung@e-tinkers:~ $ sudo apt-cache search golang|grep golang-1.*
golang-1.6 - Go programming language compiler - metapackage
golang-1.6-doc - Go programming language - documentation
golang-1.6-go - Go programming language compiler, linker, compiled stdlib
golang-1.6-src - Go programming language - source files
golang-1.7 - Go programming language compiler - metapackage
golang-1.7-doc - Go programming language - documentation
golang-1.7-go - Go programming language compiler, linker, compiled stdlib
golang-1.7-src - Go programming language - source files
golang-1.8 - Go programming language compiler - metapackage
golang-1.8-doc - Go programming language - documentation

The Better Way

The current stable version available at Golang official website is v1.12.6, and there is a distribution packaged for ArmV6 CPU available that is suitable for Raspberry Pi 3 (and some earlier models). Right click on the link that has armv6l on it to copy the link url, and type wget on Raspberry Pi terminal and paste the link to download the golang:

wget https://dl.google.com/go/go1.12.6.linux-armv6l.tar.gz

Decompress the downloaded package and move it to /usr/local directory:

sudo tar -C /usr/local -xzf go1.12.6.linux-armv6l.tar.gz
rm go1.12.6.linux-armv6l.tar.gz

The Even Better Way - Updated on 23 July, 2020

Th "Better Way" of installing Golang requires manually to to the Golang official website to find out the latest release of the software, copy the link, etc., it would be even better if all those steps can be automated. Reader Dave York recently post a link to his website where he described a shell script that he came up with for automating the process. Inspired by his work, I came up with my own shell script.

Due to the change of Google's download page structure, the script that originally published in 23 July, 2020 no longer working. The following script has been updated in April 2022 to reflect the current download page structure.

First, create the shell script with the following command:

nano go_installer.sh

enter the following shell scripts and save the file.

export GOLANG="$(curl -s https://go.dev/dl/ | awk -F[\>\<] '/linux-armv6l/ && !/beta/ {print $5;exit}')"
wget https://golang.org/dl/$GOLANG
sudo tar -C /usr/local -xzf $GOLANG
rm $GOLANG
unset GOLANG

Next make the script executable:

sudo chmod +x go_installer.sh

To run the shell script, type:

./go_installer.sh

The go_installer.sh uses curl command to get the content of Golang download page, pile it with a serial of shell commands that are basically parse the received html to find the file name of the latest stable release, and use it to run the wget command and do the rest of installation.

This script not only provide an even better way to automate the download and installation, it also make it easier to upgrade the Golang to latest version in future after your installation!

To upgrade Golang, prior running the go_installer.sh, delete your existing installation first by running

sudo rm -r /usr/local/go

Final Step - Setup path

The following steps are required even you choose to install Golang using “The Easy Way”, and the steps shown are based on Raspberry Pi OS (i.e. Raspbian), for other OS, the commands might varies.
We now need to add the PATH environment variable that are required for the system to recongize where the Golang is installed. To do that, edit the ~/.profile file:

nano ~/.profile

Scroll all the way down to the end of the file and add the following:

PATH=$PATH:/usr/local/go/bin
GOPATH=$HOME/golang

I’m going to store my Golang projects at the ~/golang directory, if you like to store it somewhere else or want to have the directory named go instead of golang, feel free to change the GOPATH=$HOME/golang to something else. Finally we need to make the system aware of the new profile.

source ~/.profile

Type which go to find out where the Golang installed and go version to see the installed version and platform.

hcheung@e-tinkers:~ $ which go
/usr/local/go/bin/go
hcheung@e-tinkers:~ $ go version
go version go1.12.6 linux/arm

Golang organizes its code files based on a pre-defined code organization structure. So let’s create the project directories:

mkdir golang
mkdir golang/src

It’s all done, and ready to write the first Go programming. I’m interested to test the shortest path algorithm that I wrote a while back using Golang to compare with the version written in Python, so stay tune for my next blog post.

26 comments by readers

  1. Hi, i was trying to install golang on my RPI4, but get stucked on the step
    $ go version
    it gives me
    bash: /usr/local/go/bin/go: No such file or directory
    even though it does exist.
    i can get the go version using sudo, but it does not seems to be a correct behaviour.
    Any suggestion?

    1. Assuming you’ve added PATH=$PATH:/usr/local/go/bin
      to your ~/.profile. This is probably because the files in /usr/local/go/bin belong to root:wheel. In my case, I don’t use the default pi user for my access, but use a username that I created that have the sudo group access. What you could try is to add the username that you are using to the sudo group:

      sudo usermod -a -G sudo username
      

      Remember to replace the username with the user that you are using for accessing the RPI.

    2. im sure you sorted this out long ago (pun intended)
      /usr/local/go/bin/
      not “/usr/local/go/bin/go” remove “go” at the end of the path

    3. In my case error was due to running on Jetson Nano in which case the architecture needs to be “arm64” and not “armv6l”. Thanks for the article.

  2. When I try to run go1.13.1 on my Raspi4 I get the following error: “bash: /usr/local/go/bin/go: cannot execute binary file: Exec format error”

    I installed go 1.11.x on my Raspi3 and that seems to run OK. It looks like Go has not been updated to Raspi4 yet.

    Is any one else having this problem?

    Thanks.

  3. I am running a Pi2 with raspian lite. I am not clear if these instructions would work on Pi1,2,3,or 4 ?

    1. Dave, your script will get rc versions. In looking at fixing that I realized I could simplify the grep/awk/sed combos considerably. I also realized I could probably make the whole thing into a one liner if I used curl -L and then piped the output of that into sudo tar -xzC /usr/local

      So a one liner way to get the latest go installed into /usr/local/go is

      curl -L https://golang.org/dl/$(curl -s https://api.github.com/repos/golang/go/git/matching-refs/tags/go | grep '/ref' | sed -e '/beta/ d' -e '/rc/ d' -e 's/.*\(go[0-9.]*\).*/\1/' | tail -1).linux-armv6l.tar.gz | sudo tar -xzC /usr/local
      
  4. I would like to add….

    If you installed a 64 bit OS (e.g. Ubuntu Server 64bit) you need to download the 64 bit code !!!

    go1.14.6.linux-arm64.tar.gz

    instead of

    go1.14.6.linux-armv6l.tar.gz
  5. If you have a Pi 4, I would strongly recommend coding in Go with Visual Studio Code. It’ s smart about installing gotools and the Intellisense support makes life a lot easier. The Pi 4 is easily beefy enough to run it. It also really pays to read the documentation on current best coding practices for writing golang code mentioned in the article, *especially* if you have been using Go prior to the module system which became the default with v1.13 (I started with Go v1.6 and had to unlearn a lot of stuff).

  6. To have a cleaner screen, u can use “-sS” parameter with curl:

    export GOLANG="$(curl -sS https://golang.org/dl/|grep armv6l|grep -v beta|head -1|awk -F\> {'print $3'}|awk -F\< {'print $1'})"
    
  7. Just wanted to let you know that your script now grabs the macOS arm package because the search variable isnt specific enough. You have to make it linux-armv6l (or linux-arm64 if you are using a Pi4 with a 64bit OS).

    Thanks for the tutorial!

  8. Here is a slightly better version of the script:

    #!/usr/bin/env bash
    
    set -e
    set -u
    set -x
    
    # download current version and extract it to /tmp/go
    export GOLANG="$(curl https://golang.org/dl/|grep linux-armv6l|grep -v beta|head -1|awk -F\> {'print $3'}|awk -F\< {'print $1'})"
    wget https://golang.org/dl/$GOLANG
    tar -C /tmp -xzf $GOLANG
    rm $GOLANG
    unset GOLANG
    
    # remove previous installation
    sudo rm -rf /usr/local/go
    sudo mv /tmp/go /usr/local
    

    Here’s a quick breakdown of the changes:

    1) I’m setting the bash shell language explicitly & exiting when either a command fails or a variable is undefined (best practice), see https://kvz.io/bash-best-practices.html for more details.

    2) When I unzip, I write to /tmp directory instead of directly writing to the end destination. This allows for several things. If any failure happens while downloading or unzipping, I don’t blow away my current installation of go.

    Here&’s the line that changed:

    tar -C /tmp -xzf $GOLANG
    

    3) I’m automating the removal of the previous golang version and moving the new version from /tmp into it’s proper place.

  9. Hi,

    thanks for the great script!

    I adopted some parts:

    – new URL to download go releases (go.dev/dl)
    – grep for linux-arm64
    – added “-sS” to curl

    #!/usr/bin/env bash
    
    set -e
    set -u
    set -x
    
    # download current version and extract it to /tmp/go
    export GOLANG="$(curl -sS https://go.dev/dl/|grep linux-arm64|grep -v beta|head -1|awk -F\> {'print $3'}|awk -F\< {'print $1'})"
    wget https://go.dev/dl/$GOLANG
    tar -C /tmp -xzf $GOLANG
    rm $GOLANG
    unset GOLANG
    
    # remove previous installation
    sudo rm -rf /usr/local/go
    sudo mv /tmp/go /usr/local
    

    Thanks,
    Thomas

  10. If it pleases the court, I wish to enter into the record, the following exhibit:

    “`
    pi@rpi400:~ $ cat /proc/sys/kernel/arch
    aarch64
    “`
    This suggests a reliable way to create a single install script is to:
    “`
    target=”$(grep -q 64 /proc/sys/kernel/arch && echo linux-arm64 || echo linux-armv6l)”
    “`
    Then you can use the `$target` variable for your search/filter/grep.

Leave a Reply to H Le Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.