What we've written in Go at work and how it came about (as of January 2020)
In comments on yesterday's entry, Joseph asked about what we're using Go for here at work. As it happens, there's a story or two here, because the starting point is that some years ago we decided to standardize on using only a few languages for our internal tools (later updated to switch to Python 3) and Go was not one of those languages. This wasn't because I didn't like Go (I've used it for a fairly long while); instead it was a tradeoff. Go didn't bring anything strongly useful for what we were doing and it would have been another language and toolchain for my co-workers to learn and deal with.
(Systems and tools we adopt from the outside can be in anything because we don't write and maintain them ourselves; they're mostly black boxes. As it happens, a lot of Prometheus related programs are written in Go, so in that sense we're running and using a fairly significant amount of Go code in production. But it's not our Go code.)
The first thing we wrote in Go was a SSH host key checker that
is a core part of our local NFS mount authentication system. In one mode of operation,
this checker has two challenges; we want to check a lot of machines
at once in as short a time as possible, and doing the SSH handshake
involves cryptography and so is somewhat CPU intensive. Since Go
has reasonably CPU-efficient native code cryptography and a great
story for parallelism, it was clearly the easiest way to write an
efficient and fast program to do this. Python with threading or
some sort of
select() multiplexing would have been more awkward
and likely taken significantly more CPU on our fileservers, and I didn't want to think about
writing a security sensitive program like this in C with threading and
third party SSH libraries.
The other two pieces of locally written Go that we're running are both part of our Prometheus metrics system, which makes them somewhat optional; if they don't work, we just miss some secondary metrics, and if they malfunction we can turn them off. One generates SNTP metrics (using code adopted from a SNTP query program I wrote) and the other generates metrics from Linux's NFS mountstats. I consider both of these programs to be interesting stories about some advantages Go has.
The SNTP metrics program is basically a thin wrapper around a third party package for making SNTP queries. It's written in Go because such a package exists in the Go package ecology (and I could find it), and Go makes using third party packages easy (partly because Go compiles to a single binary that includes everything). Had there been an equivalent Python package that I could have easily found and used, the SNTP metrics program could have as well been in Python (although then we'd have had to deal with the usual hassles of having a Python program with multiple modules).
I wrote the NFS mountstats metrics program in Go because I was worried about the CPU impact of processing all of our voluminous mountstats in Python (my worry may have been misplaced). CPU efficiency is another one of Go's advantages (as seen in our SSH host key checker), although we also got to use a third party package to parse mountstats which made it easier to write.
(The package we use is also likely to be better tested and more carefully written than something I would knock together just for our own use, regardless of the language that I wrote it in.)
I have opinions on Go as compared to Python in our particular unusual environment that don't fit within the margins of this entry. The short version is that I don't feel any urge to write most new things in Go instead of Python. Python remains our routine choice; Go is for things with special needs or where it offers special benefits. Being able to basically wrap someone else's package that does all of the work is a special benefit, as is CPU efficiency and Go's great concurrency story.