Why I am using Go more

by Alexis Hope, 04 Jun 2021

I’ve been subscribed to the Go mailing list for over 10 years. But I never really dived into the language. Work requirements never pushed me in that direction. In hindsight I regret not embracing it more. There are some qualities to it that really appeal to me. Particularly after developing a passion for Typescript and Nim.

Typescript made my Javascript world pleasurable to work in. And Nim really captured my interest. Being statically typed, compiled, optionally garbage collected with a really approachable syntax :heart:. Below I’ll try to illustrate why Im choosing Go for some tasks.

Code linting

A basic example is Go built in linting with the fmt package. Its a very subtle detail but it has an impact. Requiring all code to conform to a standard prior to compiling.

Working in Javascript or Ruby we generally employ tools like eslint or rubocop to aid code cleanliness. Great tools, but they can lead to debates regarding small details in their configuration. I quite like having an immutable code format. I can hit the ground running without having to configure a linting environment to make the team happy. Deno (a modern Node runtime built with Rust and V8) has also embraced a default formatter. With this strategy every project has a reasonably consistent standard.

Configuring Node to be in a happy place

Node is great for small server applications. Frameworks like express make it simple to create a simple server function. But for me to be in a happy place with Javascript I prefer typescript which requires tsc ts-node 1. Throw into the mix jest for testing eslint as previously mentioned for code quality. Then express to make routing simple perhaps some lodash because low level utility functions can be a little lacking in Javascript (they have improved a lot in recent years). Then if we want types for these libraries add to the mix @types/express @types/lodash etc for every dependency there is usually a corresponding type dependency.

Go has an amazing batteries included standard library testing, linting, basic routing utility is all an import away. In the simple services I’ve been writing, I found fewer overall packages to install. It could be the nature of the services, but it seems to hint that language is well rounded for the types of tasks it’s used for..

The call for compiled runtimes

After using containers for a while and philosophizing over languages. It dawned on me that one of the features of dynamic languages like PHP was your code wasn’t compiled. That having individual files interpreted at run time was a selling point. It meant for deployment you just FTP the file diff or fsync (predating CI/CD practices) to your runtime system. Minimizing the time to deployment saving the hassle of a large compile deploy life cycles.

But introduce containers into this equation. The deployment step now involves installing dependancies for PHP (or Ruby, Node, Python) and baking it into an image. This means we’re deploying all the files and dependancies all the time, which is good for reproducibility. But is also very similar to building a binary to distribute.

Why should I use a dynamic language if I deploy everything all the time?

Programming languages like Nim and Go in my opinion are a joy to work with. And if we are embracing containers as a mechanism for deployment why employ a dynamic language. The counter argument would be team familiarity with something like PHP therefore continue writing services in PHP. But I haven’t found Go sufficiently difficult to pick up, the cost to adopt is pretty low.

And compiling to an executable means a container doesn’t need to inherit a base linux version. You can compile in a linux container then copy to an empty layer, avoiding a hefty base image. You can make an image that is effectively the size of your binary. This also avoids N number system utilities that may be introduce a security vulnerability.

Ultimately I find using something like Go builds and tests faster than a PHP or a Ruby equivalent. With a smaller foot print making time to live a lot faster. And with an added bonus of a more scalable runtime, a little bit of a subjective statement, but generally speaking more scalable.

In Summary

There are many other benefits safety around static typing, safe concurrency. But the real reason I’m using Go is… I like it. And it fits nicely into this C like language preference I’m developing. Typescript Nim and Go are all C like (Von Neumann type languages) and trying to align myself to this spectrum of languages simplifies the scope of languages I was previously pursuing.

Footnotes

[1] To Type or Not to Type: Quantifying Detectable Bugs in JavaScript