Go for Dev & Ops

Go (or golang, as it is often called, because “Go” is a bit vague when typed into a search engine), if you haven’t heard of it, is a relatively new language for cross-platform development. It is a modern, C-style, statically-typed language that produces platform-native binaries, but still includes memory management and garbage collection.

Go is open-source, stable (currently at version 1.6, with its first stable release dating back to 2011), and it’s not going anywhere. Written by a couple of Google’s brilliant engineers, and used internally at Google at the levels of scale and reliability you would expect from a tech giant, it is an entirely different beast from something like Ruby or NodeJS. It encourages the kind of development and deployment pipeline that we should all strive for.

Software development has been moving more and more toward interpreted, dynamically-typed, single-threaded languages like Ruby and Node. It’s been moving more toward mountains of external dependencies – I’ve seen projects where more than 90% of the code was in third-party libraries. That’s a lot of other people’s technical debt and generalized implementations to absorb into your project.

Go encourages the exact opposite. It’s statically-typed, though it offers the convenience of type inference. It’s compiled, and not just to bytecode, but to native binary. It’s innately and intuitively concurrent. Its dependency management, like everything else about it, is intentionally minimalist, implicitly discouraging overuse of external libraries and frameworks.

Go, by design, at the language level, encourages a lot of really good programming practices:

  • Because the language and standard library aim for “exactly enough and no more”, developers are more likely to follow that lead with their own code. Go is the embodiment of KISS.
  • Go makes it easy and intuitive to handle concurrency through “communication instead of sharing”, keeping code cleaner and reducing the rate of defects. It also has a built-in race condition detector that can be activated when running tests or benchmarks.
  • The core Go tool chain includes support for unit tests and benchmarks, and will even include example code from your documentation to ensure it compiles and works.
  • Go has a language-level style guide, and included in the core Go tool chain is a tool (gofmt) that reformats files to fit the standard style.
  • Go omits many facets of OOP, including inheritance (though it has mix-ins), abstract classes, method overloading, operator overloading, and multi-level access control. Though useful tools in some cases, these are most frequently used to vastly over-complicate implementations. Go really wants you to just write the simplest thing that will work.

After the code is written, Go makes it very easy to set up continuous integration, including unit tests, benchmarks, linting, and test coverage. It’s trivial to have a build go on to cross-compile for every platform and architecture you might want to deploy to.

How do you deploy a Go app? Drop the executable on a server and execute it. There is no interpreter or virtual machine to install. In fact, there are no external dependencies at all unless you create them in code. Performance is excellent and resource usage is minimal – unlike, for example, Java or Ruby. The deployment footprint is about as small as it gets, and deployments are highly reliable. You suffer none of the fragility brought on by differences between versions of Java, Ruby, Python, or NodeJS – your binary runs the same regardless of the system it’s deployed to.

I won’t say that Go is perfect, or universally applicable. There are certainly use cases it is not well-suited to. For starters, Go produces console applications, not GUIs. It is not intended for building desktop applications – though there are libraries for doing so. Go also has a focus on simplicity and minimalism, and it could get difficult to manage very large code bases in Go unless you’re very careful and very smart about it.

Where Go really shines is in producing small, self-contained, single-purpose command-line tools and microservices. The Go standard library includes a multi-threaded HTTP server perfect for building a REST API server in a hurry, while still being able to stand up to production use.

What sort of things are built in Go? Let’s see: