What I like about Go
“Tell me what you like about Go”
A few weeks ago I was asked what I like about the Go language. It was during
a job interview, and at that moment I realized I hadn't really given much thought
to that, even though I use Go for almost every project for a while.
After some thought, I decided to write it down.
I share my experience from two perspectives:
- Ops perspective: on deploying and managing Go compiled programs. (Maybe my most important aspect)
- Developer perspective: on the Go language itself, the tooling, and the ecosystem.
The Ops Perspective
Performance.
For my purposes and the kind of services I write, Go offers performances that
are more than decent and it allows me to run Go programs
on small cheaper instances and limited serverless runtimes,
such as AWS Lambda Functions and Scaleway Serverless Jobs. For
serverless execution, good performance is important because I am charged based on
the execution time.
Okay, maybe Go is not as efficient as Rust or C++, but coming from
a heavy Python background, Go speed seems just stratospherical to me.
Cross-compilation is a breeze.
Ease of deployment on heterogeneous environments with multiple architectures
is paramount. I write services running in the Cloud (serverless or IaaS),
on bare-metal servers, on my laptop, and even on my Raspberry Pi 4.
With the dawn of Arm64 servers (and maybe RISC-V 64 in the future?), I need
cross-compilation that just works on my machine and the CI without turmoil.
Static binaries and containerization. As previously stated, some of my projects run on heterogeneous environments. Naturally, containerization is thus the privileged method to package and deploy my services. Containerizing Go programs is quite easy, and since Go compiles fast, multi-stage image builds are pretty fast as well. Having static Go binaries allows me to choose very lightweight base images for containers, such as Alpine Linux, without worrying about libc dependencies. My images are typically a few megabytes.
Startup time. When I work with orchestrators such as Kubernetes or AWS ECS I need containers to start fast, so rolling a new version or scaling out takes less time, which is always nice. As for serverless services that charge based on the execution time, lower startup times also mean saving money.
The Developer Perspective
The sweet spot between low-level and high-level. Before learning Go, I did a lot of Python (that I still use), which is considered a high-level language. In contrast, Go is a pretty low-level programming language, but it's certainly not as low-level as C either. I like this balance Go has. Not too low-level so I can ignore irrelevant details, but not too high-level when I need to use some low-level primitives such as atomic instructions, or want finer control of the layout of a struct.
Type system. This one is highly subjective. I like static typing because I make many obvious silly errors that can be caught at compile-time easily. Go also has structural typing, which seems more intuitive than nominal typing to me.
Ergonomic concurrent programming. That does not mean concurrent programming is easy just because of Go. Concurrent programming is hard anyway. But, Go makes concurrent programming a bit pleasant to write thanks to goroutines (no need for "colored functions") and (sometimes) channels.
Standardized tooling. Like every modern language of its generation, Go provides a standard tool to manage packages, run tests, build apps, format code, and even microbenchmark code.
No smarty-pants code. Go mostly has straightforward constructs—only. That makes code golfing harder, and I think it's a good thing.