The Origins of Go: Simplicity as a Feature

•5 min read•

Most languages try to add power by adding features. Go went the other direction. Its creators believed that the real problem in large-scale software was not a shortage of language features but an excess of them, and the complexity, slow builds, and hard-to-read code that came with that excess. So they built a language defined as much by what they left out as by what they put in. That discipline looked almost stubborn at first. It turned out to be exactly what a generation of cloud infrastructure needed.

Three veterans and a slow build

Go began at Google in 2007 and was announced publicly in 2009. Its designers were not newcomers. Robert Griesemer had worked on the V8 JavaScript engine and the HotSpot Java virtual machine. Rob Pike and Ken Thompson were giants from Bell Labs, where Thompson had co-created Unix and the C and B languages[1], and Pike had worked on Plan 9 and co-designed the UTF-8 encoding that now represents text across the entire web.

The origin story the team tells is almost mundane. They were waiting for a large C++ program at Google to compile[2], a wait that could stretch to many minutes, and they started sketching a language that would not make them wait. Google's scale had turned ordinary problems, build times, dependency management, and onboarding new engineers onto a huge codebase, into serious drags on productivity. Go was aimed squarely at those.

Simplicity as the design goal

Go's defining choice is its smallness. The language specification is short enough to read in an afternoon[3]. For years it deliberately omitted features that most modern languages considered essential, including generics, exceptions in the usual sense, and class inheritance. The reasoning was that a small language is easier to learn, easier to read, and easier for a large team to maintain, because there are fewer ways to express the same idea and fewer clever tricks to decode in someone else's code.

The team enforced consistency with tooling. The gofmt tool formats all Go code to a single standard style[4], which ended formatting debates permanently. There is one way Go code looks, and everyone uses it.

Concurrency built in

The one area where Go was generous rather than sparing is concurrency, and it reflects Pike and Thompson's background. Go makes it cheap to run many tasks at once through goroutines, which are lightweight threads managed by the Go runtime[5] rather than the operating system. You can run hundreds of thousands of them. Goroutines communicate through channels[6], following a model where you share data by passing messages rather than by locking shared memory.

Starting concurrent work is almost trivially simple.

go handleRequest(conn)

That single keyword launches a function as a goroutine. For software that spends its life handling many network connections at once, which describes most web servers and infrastructure tools, this model is a natural fit and a big part of Go's appeal.

One binary, easy deploys

Go compiles to a single self-contained executable[7] with no external runtime to install. You build your program and you get one file that you can copy to a server and run. After years of wrestling with interpreters, virtual machines, and dependency hell, operations teams found this deeply refreshing. Combined with fast compilation, static typing, and garbage collection, it made Go a comfortable language for building the kind of long-running services that sit at the core of a system.

The language of the cloud

Go's real-world victory came in infrastructure. Docker, which popularized containers, is written in Go[8]. So is Kubernetes, the system that orchestrates containers at scale[9] and now anchors much of cloud computing. Terraform, Prometheus, etcd, and a long list of other foundational tools are Go programs. When the industry rebuilt its infrastructure around containers and cloud-native patterns in the 2010s, it largely built that infrastructure in Go. The language's fast builds, easy deployment, and strong concurrency were ideal for exactly that work.

The generics debate

Go's commitment to simplicity was tested for more than a decade by one long argument: whether to add generics, a feature that lets you write code that works across many types without duplication. Many languages had it. Go users asked for it repeatedly. The team held out, unwilling to add the feature until they found a design that fit the language's spirit without wrecking its simplicity. Generics finally arrived in Go 1.18 in 2022[10], more than a decade after the first release. The long wait says a lot about the culture. The bar for adding anything to Go is high, and the default answer is no.

What it means today

Go reached its 1.0 release in 2012 with a promise of long-term compatibility[11], and it has kept that promise. It is now one of the standard choices for backend services, command-line tools, and cloud infrastructure, and it is common in job listings for platform and DevOps roles. On the web it shows up as fast, dependable API servers and as the language underneath the tools that deploy and run nearly everything else.

Go proves that subtraction is a legitimate design strategy. By refusing to pile on features, its creators made a language that is easy to learn, easy to read, and well suited to building the reliable plumbing the modern web runs on. Simplicity was not a limitation they tolerated. It was the feature.

Sources (11)
  1. Wikipedia: Ken Thompson
  2. Go Programming Language FAQ
  3. The Go Programming Language Specification
  4. Go Documentation: gofmt
  5. A Tour of Go: Goroutines
  6. A Tour of Go: Channels
  7. Go Programming Language FAQ
  8. Wikipedia: Docker (software)
  9. Wikipedia: Kubernetes
  10. Go 1.18 is released!
  11. Go version 1 is released