00:47:21
On the 14th anniversary of Go's open-source launch, co-creator Rob Pike reflects on the project's original goals, its surprising successes, and the hard lessons learned in building a language for modern software engineering.
The creation of Go was not fundamentally about designing a new programming language. The team's primary goal was to create a better way to write software at scale. The frustrations that sparked Go's development—like a 45-minute build time for a single binary—stemmed from the complexities of the software development process, not the languages themselves.
Go was conceived as a project to make building production-grade server software easier and more productive. It aimed to solve problems like:
The language was the enabler for these larger software engineering ideals, not the sole objective.
Several early, deliberate decisions were crucial to Go's adoption and long-term health.
The creation of the Go Gopher by Renee French was a masterstroke. This "goofy yet intelligent" mascot became a powerful banner for the community, fostering a spirit of technical excellence and fun. It provided a shared identity for early adopters and remains an iconic symbol at conferences like GopherCon.
Robert Griesemer's `gofmt` was transformative. It showed that automated code formatting could be done well and became a non-negotiable standard. The time saved by ending debates over style is incalculable. Furthermore, `gofmt`'s implementation as a library enabled countless other tools, from simplifiers to the coverage tool.
Even successful projects have missteps. A common theme was a failure in communication—the team thought their goals were self-evident, but they often weren't to the broader community.
Go played a significant role in popularizing concurrency in mainstream programming. However, two key mistakes were made:
This confusion likely drove some early adopters away. The 2012 talk "Concurrency is not Parallelism" helped but came too late.
Interfaces are one of Go's best-designed features. Their dynamic, implicit nature became the bedrock for composition, testing, and dependency management. However, their success "colored our thinking" and became a significant barrier to introducing generics.
The presence of interfaces meant any new form of polymorphism had to integrate with them seamlessly. This required multiple attempts, aborted implementations, and years of discussion. The eventual solution—a generalization of interfaces to sets of types—was subtle and profound, but the journey was long and fraught.
Writing the first compiler in C (in a Plan 9 style) was pragmatically the right choice for bootstrapping and rapid iteration. It allowed the team to implement novel features like segmented stacks quickly. However, this approach offended many in the language community who expected the use of LLVM or self-hosting from the start.
The translation to a Go-based compiler for Go 1.5 was the right eventual move, bringing all of Go's tooling advantages to the compiler's development. The lesson: use the best tool for the task at hand, even if it's unorthodox.
The transition to open source was a huge educational process. The team took too long to understand the best way to work with the community, leading to wasted time from mismatched expectations.
A key learning was around the team's insistence on high code quality through mandatory review before commit. This approach is more efficient but pushes more work onto contributors, who need to understand its value to feel welcome. This process has improved significantly over time.
The initial package design in the language was excellent. However, the transition to a world with external package versioning was poorly managed. The core team, familiar with Google's monorepo model, lacked experience with the complex problems of dependency graph resolution across many versions.
The process of engaging the community to solve this was well-intentioned, but the final design left many feeling slighted. The resulting system is technically excellent but took too long to arrive, and the journey was rocky.
The team wrote extensive documentation but initially failed to grasp that the community wanted examples of how to use features, not just descriptions of what they did. This was eventually corrected, and the addition of the Go Playground—an online sandbox for running code snippets—was a massive improvement.
The most significant consequence of Go's design choices is that Go code looks and works the same everywhere. It is largely free of factions using different language subsets and is guaranteed to compile and run for years to come. This combination of a strong standard library, concurrency, composition, fast tools, readability, and stability has created a uniquely consistent and productive environment for software development.