Why Go, Why Now: A 2007 Language Built for the AI Era
It's September 2007, on the Google campus in Mountain View. Three engineers are waiting for a C++ program to compile. Not a toy program: one of Google's giant server binaries, the kind that pulls in thousands of header files and takes the build farm somewhere between half an hour and forty-five minutes to churn through. You can't do much while you wait. You drink coffee. You complain.
The three engineers waiting are not ordinary engineers. Ken Thompson created Unix and the B language, the direct ancestor of C. Rob Pike co-created UTF-8 and worked on Plan 9, Bell Labs' successor to Unix. Robert Griesemer worked on the V8 JavaScript engine and studied under Niklaus Wirth, the designer of Pascal. Between them, they had been building languages and operating systems for four decades.
And the conclusion they reached, waiting on that build, was unusual. The problem wasn't the build farm. The build farm was enormous. The problem was the language. C++ made every one of Google's real problems worse: compiles were slow because of how includes worked, the language had grown so large that any two engineers used different subsets of it, and its concurrency story was bolted on at a time when every new server had more cores than the last one and nobody's code was using them.
So while the compiler ran, they started sketching a new language. They had a name for it by the end of the day. Go.
The problem was never syntax
Here's the thing that makes Go different from most languages, and it's the single most useful idea to carry through this course.
Most languages are designed around the question: how do we make code easier to write? More expressive type systems, more powerful abstractions, more ways to say the same thing more elegantly.
Go was designed around a different question: what happens to code after it's written? At Google, the answer was visible everywhere. Code outlives its author. The person debugging your service at 3am is not you. A codebase has thousands of contributors, and engineer number 4,001 has to read code written by engineers one through 4,000. At that scale, a language's writing experience barely matters. What matters is whether a stranger can open any file in the repository and understand it.
Rob Pike later put it directly: Go is a language designed in the service of software engineering. Not programming-language research, not elegance for its own sake. The day-two problems: building, reading, maintaining, and changing software with many hands over many years.
Hold onto that frame: Go optimizes for the reader. Every design decision in the language falls out of it. And, as we'll see at the end of this lesson, it's also why a 2007 language is having its best moment in 2026.
Built by subtraction
When Go came out, the loudest criticism was everything it didn't have. No inheritance. No exceptions. No operator overloading. No ternary operator. For years, no generics. Critics called it a language stuck in the 1970s.
Every one of those omissions was a decision, and they all serve the reader.
The spec is small. Go has exactly 25 keywords. C++ has nearly a hundred, and that's before templates. You can read the entire Go language specification in an afternoon, and people actually do. A small language means the code you encounter in the wild uses the same constructs you learned, not a dialect you've never seen.
There is one way to do most things. Go has a single loop construct: for. It covers while-loops, infinite loops, and iteration. There's no argument about which loop to use because there's nothing to argue about. Multiply that by every feature in the language and you get Go's signature property: two Go programmers, given the same problem, tend to produce eerily similar code. That sounds boring. It is boring. It's also exactly what you want when your job is reading code someone else produced.
Formatting is not your problem. Go ships with a tool called gofmt that reformats your code into the one canonical style. There's no configuration. There are no options. Tabs versus spaces, brace placement, alignment: all settled, permanently, for everyone. Entire categories of code review comments simply don't exist in Go. Twenty years of style guide arguments, deleted by one tool.
Errors are values, not surprises. In most languages, errors travel through an invisible side channel: exceptions that can erupt from any line and teleport control flow to a handler three files away. Go made errors ordinary values that functions return, and you handle them right where they occur:
data, err := os.ReadFile("feeds.json")
if err != nil {
return fmt.Errorf("loading feeds: %w", err)
}Read those four lines as a reader, not a writer. The function might fail. You can see that it might fail. You can see what happens when it does. Nothing is hidden. Yes, you'll write if err != nil hundreds of times in this course, and yes, it gets verbose. But every failure path in a Go program is visible on the page, which means every failure path can be reviewed. File that thought away; it becomes important shortly.
Compiles are fast. This was a founding requirement, not a nice-to-have. Go's package and import system was designed specifically so the compiler never re-reads what it doesn't need (the C++ include model, the thing that caused the 45-minute wait, was the villain here). Real Go services compile in seconds. You'll feel this every single lesson: change, build, run is a loop measured in single-digit seconds, and that loop is where learning happens.
The concurrency bet
There's one place where Go added rather than subtracted, and the timing tells you why.
In 2007, the free lunch was ending. For decades, single-core clock speeds doubled every couple of years and your code got faster without you doing anything. Around 2005 that stopped: chips hit physical limits, and manufacturers started shipping more cores instead of faster ones. All new compute was parallel compute, and mainstream languages handled this with threads and locks, which are notoriously easy to get wrong and miserable to debug.
Go's designers reached back to an idea from 1978: Tony Hoare's Communicating Sequential Processes, which Rob Pike had spent twenty years exploring in earlier languages at Bell Labs. Instead of sharing memory and guarding it with locks, you run lots of small independent processes that talk to each other through channels. In Go these became goroutines, which are so cheap you can run a million of them on a laptop, and channels, typed pipes that goroutines use to pass values to each other safely.
The crucial part is that this was built into the language itself, with its own keyword, not bolted on as a library. Starting a concurrent task in Go is one word: go fetchFeed(url). We're deliberately not going deeper than that sentence today. Module five of this course is six lessons on exactly this machinery, and by then you'll have a real program that needs it.
The promise that paid off
Go went public in November 2009, and in March 2012 the team shipped Go 1 along with a document that did more for the language than any feature: the Go 1 compatibility promise. Code that compiles under Go 1 will keep compiling under every future Go 1.x release. A program written in 2012 builds today, on Go 1.27, fourteen years later, usually without touching a line.
If you've lived through Python 2 to 3, or a JavaScript framework migration, you know how rare that is. Companies noticed. You could bet a codebase on Go and the ground wouldn't move under you.
And then Go quietly won an entire layer of the industry. In 2013, a small company rewrote its container tool in Go: Docker. In 2014, Google open-sourced its cluster orchestrator, written in Go: Kubernetes. Terraform, Prometheus, etcd, CockroachDB, Caddy, esbuild. The tooling that builds, ships, deploys, monitors, and scales modern software is, to a remarkable degree, written in one language. Nobody announced that the cloud would be written in Go. It just happened, one infrastructure project at a time, because the language was fast enough to matter, simple enough for big teams, compiled to a single static binary you could drop anywhere, and never broke its users.
That's where Go stands today: the default language of cloud infrastructure, backend services, and command-line tools. Learning it has been a safe career bet for a decade. But that's not why this course exists now.
Why now: the language of the AI era
Think about how you'll actually write code over the next decade. An AI assistant writes the first draft. You describe what you want, code appears, and your job shifts from typing it to judging it: is this correct, is it safe to ship, does it handle the failure cases? The bottleneck in software is moving from writing code to reviewing it.
Now replay everything this lesson said about Go, with that shift in mind.
Go optimizes for the reader, and you've just become a full-time reader. The language designed so that engineer 4,001 could review code written by 4,000 strangers is precisely the language for reviewing code written by a model. There's one idiom, so AI-generated Go looks like all other Go: no clever dialect to decode, no surprise metaprogramming, deviations stand out visually.
The toolchain is mechanical, so the feedback loop closes itself. gofmt normalizes the style. go vet flags suspicious constructs. The compiler enforces types. The race detector catches concurrency bugs. Every one of those checks is a program, which means an AI coding agent can run them, read the errors, and fix its own output before you ever see it, in compile cycles that take seconds, not the better part of an hour. The properties Go's designers wanted for Google's build farm in 2007 are the exact properties that make an AI agent's loop converge in 2026.
And errors are values, sitting right there on the page. When you review AI-written Go, every failure path is visible in the diff. There is no invisible exception channel to audit, no hidden control flow to reason about. The most error-prone part of machine-generated code, what happens when things go wrong, is the part Go forces into the open.
Here's the framing worth remembering: a Google-scale codebase and an AI coding assistant present the same engineering problem. Lots of code, written by many hands that aren't yours, that you must be able to read, verify, and maintain. Go was built for that problem seventeen years before it became everyone's problem.
Boring on purpose
Let's be honest about the trade, because this course will be honest throughout.
Go is verbose. You will write if err != nil until your fingers learn it as a single gesture. Go is conservative: generics didn't arrive until 2022, a full thirteen years after release, because the team refused to add them until they had a design that didn't compromise the rest of the language. And Go is not for everything. Nobody's building native UIs in it, data science lives in Python, and if you want a type system you can prove theorems in, Rust and Haskell are down the hall.
Go's bet is that boring is a feature. The language is small enough to stop thinking about, and that's the point: your attention goes to the system you're building, the data flowing through it, the failure you didn't anticipate. After the first few lessons, Go mostly disappears. What's left is the problem.
The road ahead
This course has one through-line. Starting in module two, you'll build feedstack: a feed aggregator that begins life as a tiny command-line program fetching a single feed, and grows, lesson by lesson, into a tested, configured, concurrent HTTP service that fetches dozens of sources at once, dedupes them, and serves a combined feed. Every language feature you learn exists because feedstack needs it. By the closer, you'll have built and tested a real Go service end to end.
Six modules get you there:
- getting to hello · the toolchain and your first compiled program
- the building blocks · values, control flow, functions, pointers, slices, maps, structs
- talking to the world · errors, files, io, and calling real APIs
- modeling with types · methods, interfaces, embedding, generics
- doing many things at once · goroutines, channels, select, context, sync
- shipping it · testing, fuzzing, project structure, the HTTP server, observability
Next up: getting Go onto your machine. There's a tool that makes installing language toolchains almost unfairly easy, and it's the same one you'll use for every language after this. Toolchain tour, next lesson.
Photos in the lesson video via Wikimedia Commons: Ken Thompson by A.C.Diller (CC BY-SA 4.0), Rob Pike by Chlor (CC BY-SA 3.0), Robert Griesemer by Eugene Zelenko (CC BY-SA 4.0).