I strive to respect everybody’s personal preferences, so I usually steer clear
of debates about which is the best programming language, text editor or
operating system.

However, recently I was asked a couple of times why I like and use a lot of Go, so here is a coherent article to fill in the
blanks of my ad-hoc in-person ramblings :-).

My background

I have used C and Perl for a number of decently sized projects. I have written
programs in Python, Ruby, C++, CHICKEN Scheme, Emacs Lisp, Rust and Java (for
Android only). I understand a bit of Lua, PHP, Erlang and Haskell. In a previous
life, I developed a number of programs using
Delphi.

I had a brief look at Go in 2009, when it was first released. I seriously
started using the language when Go 1.0 was released in 2012, featuring the Go 1
compatibility guarantee. I still have
code running in production which I
authored in 2012, largely untouched.

1. Clarity

Formatting

Go code, by convention, is formatted using the
gofmt tool. Programmatically formatting code
is not a new idea, but contrary to its predecessors, gofmt supports precisely
one canonical style.

Having all code formatted the same way makes reading code easier; the code feels
familiar. This helps not only when reading the standard library or Go compiler,
but also when working with many code bases — think Open Source, or big
companies.

Further, auto-formatting is a huge time-saver during code reviews, as it
eliminates an entire dimension in which code could be reviewed before: now, you
can just let your continuous integration system verify that gofmt produces no
diffs.

Interestingly enough, having my editor apply gofmt when saving a file has
changed the way I write code. I used to attempt to match what the formatter
would enforce, then have it correct my mistakes. Nowadays, I express my thought
as quickly as possible and trust gofmt to make it pretty
(example of what I would type, click
Format).

High-quality code

All standard library code which I have read so far was of extremely high quality.

One example is the image/jpeg package: I
didn’t know how JPEG worked at the time, but it was easy to pick up by switching
between the Wikipedia JPEG article and the
image/jpeg code. If the package had a few more comments, I would qualify it as
a teaching implementation.

Opinions

I have come to agree with many opinions the Go community holds, such as:

Variable names should be short by default, and become more descriptive the further from its declaration a name is used.

Few keywords and abstraction layers

In my experience, the small number of abstraction layers and concepts makes the
language easy to pick up and quickly feel comfortable in.

While we’re talking about it: I was surprised about how readable the Go
specification is. It really seems to target
programmers (rather than standards committees?).

2. Speed

Quick feedback / low latency

I love quick feedback: I appreciate websites which load quickly, I prefer fluent
User Interfaces which don’t lag, and I will choose a quick tool over a more
powerful tool any day. The
findings
of large web properties confirm that this behavior is shared by many.

The authors of the Go compiler respect my desire for low latency: compilation
speed matters to them, and new optimizations are carefully weighed against
whether they will slow down compilation.

A friend of mine had not used Go before. After installing the
RobustIRC bridge using go get, they concluded that Go
must be an interpreted language and I had to correct them: no, the Go compiler
just is that fast.

Most Go tools are no exception, e.g. gofmt or goimports are blazingly fast.

Maximum resource usage

For batch applications (as opposed to interactive applications), utilizing the
available resources to their fullest is usually more important than low latency.

It is delightfully easy to profile and change a Go program to utilize all
available IOPS, network bandwidth or compute. As an example, I wrote about
filling a 1 Gbps
link,
and optimized debiman to utilize all
available resources, reducing its runtime by hours.

3. Rich standard library

The Go standard library provides means to effectively
use common communications protocols and data storage formats/mechanisms, such as
TCP/IP, HTTP, JPEG, SQL, …

Go’s standard library is the best one I have ever seen. I perceive it as
well-organized, clean, small, yet comprehensive: I often find it possible to
write reasonably sized programs with just the standard library, plus one or two
external packages.

Domain-specific data types and algorithms are (in general) not included and live
outside the standard library,
e.g. golang.org/x/net/html. The
golang.org/x namespace also serves as a staging area for new code before it
enters the standard library: the Go 1 compatibility guarantee precludes any
breaking changes, even if they are clearly worthwhile. A prominent example is
golang.org/x/crypto/ssh, which had to break existing code to establish a more
secure
default.

4. Tooling

To download, compile, install and update Go packages, I use the go get tool.

All Go code bases I have worked with use the built-in
testing facilities. This results not only
in easy and fast testing, but also in coverage
reports being readily available.

Caveats

Of course, no programming tool is entirely free of problems. Given that this
article explains why Go is my favorite programming language, it focuses on the
positives. I will mention a few issues in passing, though:

If you use Go packages which don’t offer a stable API, you might want to use a specific, known-working version. Your best bet is the dep tool, which is not part of the language at the time of writing.

Idiomatic Go code does not necessarily translate to the highest performance machine code, and the runtime comes at a (small) cost. In the rare cases where I found performance lacking, I successfully resorted to cgo or assembler. If your domain is hard-realtime applications or otherwise extremely performance-critical code, your mileage may vary, though.

I wrote that the Go standard library is the best I have ever seen, but that doesn’t mean it doesn’t have any problems. One example is complicated handling of comments when modifying Go code programmatically via one of the standard library’s oldest packages, go/ast.