GoLang - Quick-Start Using Docker

Intro

You want to get your hands dirty quickly with GoLang without having to install or configure it locally? I invite you to continue reading ...

Instead of trying to run things locally polluting our machine, I always prefer running things via docker if possible. That is also how I do it in this post.

Prerequisites

  • A Shell (Linux / MacOS / WSL2 / VM)
  • Docker

Run Go Without Installing It

1.  Let's create a script that will act like the go cli as a basis for running other go commands we will need:

#!/bin/bash
# change directory to where this script is located inside of
cd "${0%/*}"
root_dir="$(pwd)"

# allow for using a different version
version="${VERSION:-1.19}"

container_app_dir="/app"
container_cache_dir="output/cache"
container_gopath_dir="gopath"
cache_dir="${root_dir}/${container_cache_dir}"

if [ ! -d "${cache_dir}" ]; then
  mkdir -p "${cache_dir}"
fi

docker run --rm \
  -u $(id -u ${USER}):$(id -g ${USER}) \
  --workdir "${container_app_dir}/src" \
  --volume "${root_dir}:/${container_app_dir}" \
  --env "GOCACHE=${container_app_dir}/${container_cache_dir}" \
  --env "GOPATH=${container_app_dir}/${container_gopath_dir}" \
  golang:${version} go $@

2.  We need to save it as a file we call "go" and make it executable:

_> chmod +x ./go

3.  And now we can run go commands:

_> ./go version

Hello World

Now that we can run go, let's write some code.

1.  Create a directory ./src which we will use to write all our code inside.

2.  Create a file called main.go with the following contents:

package main

import (
    "fmt"
)

func main() {
    fmt.Println("Hello there!")
}

This program will print out "Hello there!" when executed

Build & Run

Now that we have some code let's make a script that will make it easy for us to build and run our code.

1.  Create a file called build-and-run with the following contents:

#!/bin/bash
# change directory to where this script is located inside of
cd "${0%/*}"

./go build -v -o "../output/" main.go \
  && ./output/main

This will build our code and save the output i.e. the program under output/main and run it.

Make it executable:

_> chmod +x ./build-and-run

2.  Now you can run the compiled program:

_> ./build-and-run
Hello there!

Adding Dependencies

We don't want to write all the code ourselves because others probably solved many problems already and made the solutions available as open source libraries / packages.

1.  Create a file called "get", make it executable (chmod +x ./get) and add the following contents:

#!/bin/bash
cd "${0%/*}"

if [ ! -f "./src/go.mod" ]; then
  ./go mod init main
fi

./go get $@

2. Add a new dependency by running the script:

_> ./get github.com/jakehl/goid

This will download the goid (uuid package) into the gopath directory under pkg and a reference of it will be added to the file src/go.mod

3.  Use the library in your code (src/main.go):

package main

import (
    "fmt"
    "github.com/jakehl/goid"
)

func main() {
    fmt.Println("Hello there!")
    uuid := goid.NewV4UUID()
    fmt.Println("This is a UUID: ", uuid)
}

4.  Build and run the code:

_> ./build-and-run
Hello there!
This is a UUID: 659730b1-aab0-44ff-afa0-91897f117c40

Dependencies Location

If we look closer at the our first docker helper script, we can find following:

container_app_dir="/app"
container_gopath_dir="gopath"
docker ...
...
--volume "${root_dir}:/${container_app_dir}" \
--env "GOPATH=${container_app_dir}/${container_gopath_dir}"
...

With the --env docker argument we are telling go to set the GOPATH to /app/gopath which will be just gopath in our workspace directory because of the volume mounting.

To get benefits from the editor of our choice we need to tell the editor / IDE what is the GOPATH i.e. packages location.

You can check how to do this by reading following examples for vscode or goland:

Tidy Up

Go can remove unused or install missing dependencies based on the code and the go.mod file.

Here is a script you can use as a helper to tidy up (you can call the script "tidy"):

#!/bin/bash
cd "${0%/*}"

if [ ! -f "./src/go.mod" ]; then
  ./go mod init main
fi

./go mod tidy

Don't forget to make it executable with chmod +x ./tidy.

The GitHub Repository

You can view the result of the above steps in this github repository

That's It

Often we would like to try out something quickly but without going through the hassle of local installation and configuration. I hope this guide helps you trying out GoLang quickly and easily.

Adnan Mujkanovic

Adnan Mujkanovic

Full Stack Overflow Developer / YAML Indentation Specialist / Yak Shaving Expert
Gotham City