The Doors Go Has Opened

Go has quickly become the most popular and successful systems programming language of the last 10 years.

Go is bringing Gotham, and distributed systems, out of the darkness. Credit Ashley McNamara and Renee French

Before Go, C, C++, Java, and C# were the big dogs in the systems programming world. Go is still a baby even today, but it’s coming for you.

It’s opened up a new world of open source software. It was the perfect language that came at the right time, and it’s sparked a new era of computing. All of this high-profile software is written in Go:

  • Kubernetes: a container orchestrator used in production by large companies to run distributed services. Other companies have been started around building, hosting and supporting this software
  • etcd: a strongly consistent key/value store. It’s used in mission critical distributed systems and in practice has become the open-source equivalent of Google’s Chubby. It’s a central component of Kubernetes
  • Docker: the most popular container runtime on the market right now. Also a central component of Kubernetes

Cloud Native wouldn’t be possible without Go, and neither would the Cloud Native Computing Foundation. And that’s just to start. Go is taking over other parts of open source too, not to mention major parts of the internal infrastructure of big companies.

Here’s why practically everyone in open source (and elsewhere) is choosing Go to build, and rebuild, production systems and big software.

Toolchain

Everyone who tries Go starts with the Go playground. You go to a website, write some code, and run it. Nothing to install, works everywhere, and a great first-time experience.

Whatever you’re building, you focus on building it. Go already figured out the tooling for you

Then you download the toolchain — a single binary called go. You can run go build and you get production-grade software ready to run. No learning the GCC toolchain, clang, linux shared objects, the JVM, or anything else.

Whatever you’re building, you focus on building it rather than the tools you need. Go already figured them out for you.

You can spend your time and energy solving real problems and building real products.

A Single Binary

With the old dogs, you compiled your code but you couldn’t just run it. It needed something else on the system to run: shared objects, a JVM, and so on.

Just ship a binary to your server and you’re done

go build spits out a single binary ready to run. Publish it and ship it to your servers. It works because it has everything you need compiled right into it.

This simple fact has powerful implications. The best thing about it is that your deployment process can be so much simpler than before— just ship a binary to your server and you’re done.

You can even build for different OSes with a few environment variables. This feature is great for CLIs. Some of the most successful ones:

  • etcdctl: the CLI for etcd
  • kubectl: the CLI for Kubernetes
  • docker: the CLI for the Docker server
  • dep: the CLI for the new Golang package manager

Concurrency

The cloud isn’t new anymore, it’s the standard. VMs and containers live and die without notice, streams of data come and go non-deterministically, and RPCs are sent and retried constantly.

Instead of wrestling with threads, you put 'go’ in front of a function and it’s running concurrently

For modern software to work properly and efficiently, it needs to handle all these events concurrently. Distributed, fault-tolerant architectures are the norm today.

With the old dogs, you had to deal with OS threads, locks, condition variables and so on. Getting to the point of being able to write an efficient, resilient system meant learning — or inventing — a concurrency framework before you could move on.

Now you get built-in primitives that are easy to understand. Goroutines and channels make sense because they mimic the real world.

The end result is that you put go in front of a function and it’s running concurrently. You can easily understand all this concurrency and again you can focus on building your product. Seeing a trend?

Go has unlocked powerful distributed systems because it makes concurrency radically easier than before.

That’s why we’re seeing more resilient, faster and more CPU efficient software. With Go, you can actually build stuff that you read in research papers.

Garbage Collection

GC is a controversial topic for Go and systems programming in general.

We can have a systems programming language and GC at the same time

In C/C++ land, you have complete control over memory. You decide when and how you allocate and release memory. The JVM has gone the other way and given up this control by shipping a garbage collector.

Overall, GC is convenient, but stop the world times have bitten lots of folks. Hard.

Manually managing memory is hard, and harder still when you have concurrency going on. Before Go, we were stuck with conflicting challenges: we needed a framework that won’t leak memory or break your program, but it had to make sense to programmers.

The end result was millions of libraries that make different tradeoffs and always force you to think about your program in a unique, specific way.

Go took a stand and said:

  1. Nothing will ever be easier than not having to think about memory
  2. We can “sit in the middle” and build a systems programming language with GC

Go is a systems programming language with GC. Hell has frozen over.

The reality is that GC has been a huge driver for Go’s explosion. There are edge cases in Go’s garbage collector that can cause problems for some. But lots of thought has gone into making it work properly — by default — for 90% of programs.

If you do hit that 10%, you can turn some knobs, and even that’s a lot easier than tuning the JVM garbage collector.

Standard Library

The Go standard library is one of the best in the biz. It’s not huge but it covers 80% of use cases, and it’s not complex but it lets you do complex things.

The ethos is all about agreeing on ideas, codifying them, and reusing them

Popular Go packages are high quality because they’re built on the high-quality standard library.

More importantly than the standard library’s code is its ethos. Generally speaking, it encourages the reuse of interfaces and idioms. Examples:

  • io.Reader and io.Writer are the ways to “pipe” data across function boundaries. These interfaces are probably the most implemented across the entire Go ecosystem
  • context is the way to provide cancellation, timeout, and value propagation semantics to goroutines
  • error is the way to return and describe errors from functions

Packages generally agree on these and other common idioms, and so they work together smoothly.

The ethos is all about agreeing on ideas, codifying them, and reusing them.

Conclusion

I said in the beginning of this article that Go is the perfect language that came at the right time.

Go will become the standard programming language for several large domains in software engineering

I’ve explained why, but the bottom line is that Go has made the right things easy enough to unlock some of the most powerful and advanced software we’ve ever seen in open source.

I expect Go to continue becoming the standard for other use cases — frontend servers (replacing Rails/Node.js), CLIs (replacing many scripting languages), and maybe even GUIs and mobile apps.

The language just hit its 8 year anniversary, and its rise has been meteoric. But the next 8 years are going to be ten times bigger.

Go will become the standard programming language for several large domains in software engineering.