Go global variables

Let’s face it. Global variables are mostly bad and you should not use them. BUT they are cases where it’s better to use them. This post will explore these. Sentinel errors In Go, you don’t throw and catch errors. You wrap and return them, and check them with errors.Is(err, errSomething). You may wonder what errSomething is? It’s a sentinel error. The error check errors.Is(err, errSomething) will return true only if errSomething is the same error variable as err or as the one wrapped in err....

May 27, 2022 · 4 min · Quentin McGaw

Go errors with codes

In a hurry 🏃? Jump to the conclusion After some discussion on Reddit, I decided to write this blog post on how to have Go errors containing codes you can use in calling layers. This is the case for example if you want to have the HTTP status code contained in an error created in your database package. Let’s start with some base code showing how this works. You have two files:...

September 18, 2021 · 2 min · Quentin McGaw

Wrap Go errors like it's Christmas!

In a hurry 🏃? Jump to the conclusion It took me months if not years to figure out the best way to wrap errors in Go. This was even more critical when developing public Go APIs where a user should be able to check for your (returned) errors. Global variables and errors NEVER USE GLOBAL VARIABLES!… except for errors which are meant to be constants. For example: var ErrUserNotFound = errors....

September 15, 2021 · 4 min · Quentin McGaw

Faster Go development lifecycle with Go 1.16's embed

This post concerns my most popular Github repository: github.com/qdm12/gluetun. This is a VPN client application written in Go and meant to be ran in Docker. Because it is a security and privacy focused application, all VPN servers information including their IP addresses have to be bundled in the program. This is to avoid using hostnames and leak an initial DNS resolution resolving the VPN server hostname. Arguably, because gluetun runs in a container, this information could also be stored in the Docker image and read at runtime....

July 20, 2021 · 5 min · Quentin McGaw

Fast thread-safe randomness in Go

This post is about how to generate uniformly distributed numbers thread safely and as fast as possible. It does involve randomness but we do not aim at generating cryptographically secured random numbers. The use cases vary, but a common example is to pick an element from a slice uniformly for each HTTP request in an HTTP server. Given the way the net/http library is, one cannot fiddle with the entrypoint before the request handling is launched in its own goroutine....

July 10, 2021 · 10 min · Quentin McGaw

Binpot

binpot is the repository holding Dockerfiles and Github workflows to statically build binaries for all CPU architectures supported by Docker. TL;DR ⏩ Usage: FROMalpine:3.14COPY --from=qmcgaw/binpot:helm /bin /usr/local/bin/helm Programs available Search programs on Docker Hub All Docker images and programs are built for every CPU architecture supported by Docker Initial situation 🤔 I developed VSCode development containers Dockerfiles for amd64 only, which covers most machines....

June 28, 2021 · 7 min · Quentin McGaw

Alpine: why wget and not curl?

Alpine is tiny. The alpine:3.14 Docker image is only 5.6MB uncompressed on amd64. Alpine achieves this partly thanks to busybox, which Docker image busybox is only 1.24MB. Alpine comes with wget implemented in its Busybox multi-call binary. You can try it with: docker run -it --rm busybox wget But why isn’t curl implemented as well, or instead of wget?? 🤔 wget vs curl The following table shows some key differences between the two, comparing the two installs on Alpine by using...

June 25, 2021 · 3 min · Quentin McGaw

The Go Dockerfile

There are various ways to organize your Dockerfile and CI. After having tried many solutions, I have a solid way to write your Dockerfile for your Go program. The Dockerfile is also heavily optimized for the Docker layer caching mechanism, to have fast rebuilds locally and on your CI. In this post, we will analyze such Dockerfile and analyze the structure of it, which is optimized for caching, secured and designed to contain everything....

June 5, 2021 · 11 min · Quentin McGaw

Go project structure

There is no right way to structure a Go project. But there is a best way to have a structured, clear and maintainable Go project structure. After seeing so many wrong-doings in the file structure of a Go project, making it unmaintainable, I thought it was time to write a post on that. We will examine what this structure is, why and what to avoid. The file structure In the following, we assume your application name is myapp and the project name is github....

June 5, 2021 · 5 min · Quentin McGaw

VSCode Go development container

In April 2019, VSCode released a new extension Remote Containers Development allowing you to code with your development environment in a Docker container. After having struggled somehow to install all the proper tooling for Go on my host, that looked like the perfect occasion to jump in. That is why I developed the Docker image qmcgaw/godevcontainer together with devtainr to have a blazing fast installation. The following diagram will explain the remote container development concept much better than I can ever explain it:...

June 5, 2021 · 3 min · Quentin McGaw

Cross CPU docker images using Go

Building cross CPU Docker images for Go programs is not a trivial task. With the excellent Go compiler and the recent improvements of Docker building, quite an advanced setup can be achieved to build Docker images for all CPU architectures supported by Docker and Go. What we’ll do We will design a Dockerfile cross building a simple Go program for Docker images supporting multiple CPU architectures. The aim is to have the statically compiled Go program in a final Docker image based on the alpine:3....

June 4, 2021 · 4 min · Quentin McGaw