15 Reasons I Love Go
Go became known for its built-in concurrency and the absence of inheritance. But Go has many more advantages than these. I collected 15 of them here. Each of them might not seem world-shaking when looked at in isolation, but taken together, they build a unique composition of features that make Go the language we Gophers could love to pieces.
Use these reasons as a decision aid. They are unbiased, guaranteed! ;)
Table of contents
1. The Boring Language
Go's simplicity and lightweight syntax make it an easy language to learn and adopt, especially for newer programmers.
Unlike some languages, Go avoids complex features and minimizes bells and whistles. Developing in Go feels like a breath of fresh air, enabling you to focus on solving problems rather than wrestling with the language itself.
Go's simplicity and “boringness” make it the language of choice for mixed teams. Quoting Jonathan Hall, “I can take a group of juniors and seniors and put them together, and they can be productive together, without having to spend months ramping up the juniors to understand all the arcane syntax in a language.”
If you're looking for a modern language that gets out of your way, Go is your choice.
2. A crazy fast compiler
One of Go's standout features is its unbelievably fast compiler. We're talking seconds for even large codebases.
This super quick feedback loop improves developer productivity tremendously. You don't waste precious time waiting for bloated builds. Instead, you can iterate rapidly and use the time saved to add more value to your programs. It's almost like using an interpreted language.
For this reason alone, Go is worth adopting if you value fast development speed.
3. Go collects your garbage
Go's built-in garbage collection eliminates the need for manual memory management, making Go far easier to program than languages like C and C++.
As a developer, you don't have to worry about freeing memory or tracking allocations. The garbage collector handles all of that for you with highest efficiency and predictable low latency. Programming in Go feels like a relief, knowing you can focus on high-level app logic rather than nitty-gritty memory details.
This simplicity is one reason Go is loved by so many developers today!
4. Concurrency made easier
Concurrency is baked into Go, unlike many other languages.
Goroutines and channels make it substantially easier to write asynchronous code that fully utilize multicore processors. Go uses a model called CSP that makes concurrency much easier to reason about. Concurrency is the future as Moore's Law ends, and Go makes it more approachable.
If you need to build high-performance backends and systems, Go's excellent concurrency support is a must-have feature.
5. Scalable apps
Go was designed from day one for scalability.
Its hyper-lightweight threads (a.k.a. goroutines) and built-in concurrency features allow Go programs to take advantage of multicore CPUs and distributed computing clusters. Go handles all the scheduling of goroutines behind the scenes, enabling you to focus on your program's logic and architecture.
Some of the world's most demanding and highest-traffic systems are built with Go, including Docker, Kubernetes, CloudFlare, and Dropbox. If you need scalability, check out Go!
6. Catch errors at compile time
Go is a statically typed language like Java or C++.
This means that variables have a fixed type known at compile time, rather than changing dynamically like in Python. Static typing catches errors earlier in the dev process and improves runtime performance since types don't need to be checked at runtime.
Moreover, static typing means better self-documentation. And Go's type inference keeps the syntax simple. You get safety and speed without the verbosity.
For any large program, static typing is a must-have feature.
7. The standard library
Go ships with a robust, production-ready standard library, so you can be productive right away.
The standard library provides high-quality implementations for things like HTTP servers, JSON parsing, cryptography, and more.
No need for stitching together external libraries or reinventing the wheel. The standard library is cross-platform and has bindings for Windows and Linux systems programming.
Whether building a web app, utility, or system tool, you can get quite far with Go's standard library.
8. Mechanical sympathy
Even though Go is garbage collected, it provides low-level access to memory and pointers like C for high-performance use cases.
You can pass pointers to avoid copying data and write superfast programs that run closer to the metal.
Go gives you the control when you need it. Unlike many managed languages, Go recognizes that sometimes you require expressive low-level access to memory and internals for the hottest code paths.
Go helps write your code with sympathy for the underlying platform to extract the highest performance. If the (highly efficient) garbage collection cycles get in your way (in 99% of the cases, they don't), zero-allocation techniques keep critical paths GC-free.
9. Interfaces over inheritance
Interfaces in Go provide powerful polymorphism and abstraction capabilities.
You can hide concrete implementation details behind simple interfaces. Types in Go implicitly satisfy interfaces by implementing the required methods. This enables loose coupling between components.
Inheritance is a paradigm whose costs (in terms of mental burden) far outweigh its perceived benefits. Interfaces and composition can achieve the same with less overhead.
Interfaces are everywhere in Go - io.Reader
, http.Handler
, and more, are part of the standard library and help abstract away technical details. They are a key part of idiomatic Go code to decouple software elements and enable clean architecture and design.
10. Cross-compiling, static binaries, no VM
Unlike some languages, Go compiles down to static machine code rather than bytecode or being purely interpreted.
This means you can trivially build Go programs for many platforms like Linux, macOS, and Windows. There's no need for virtual machines or interpreters. The compiled executables can be linked into C programs too.
All Go dependencies of an app are available as source code. Go therefore compiles trivially to fully static, self-contained binaries. Even non-Go dependencies can be linked statically for maximum independence from the execution environment. (Goodbye, runtime dependency hell.)
Go's cross-platform abilities make deploying and shipping software simple. A binary with no dependencies can run anywhere. Cross-compilation even allows compiling a binary on Windows for Linux, or on Linux for BSD, or on macOS for Windows, without the need for installing toolchains of the target platform. That's a massive advantage for ops and infrastructure management.
11. The Go toolchain
I love Go's toolchain. It is fairly complete and well-thought-out, and it significantly improves the development experience as a whole, as well as in small details.
For example, the built-in formatting tool gofmt
automatically styles your code consistently. No more arguing over tabs versus spaces, or the placement of curlies!
Dependency management, testing, benchmarking, profiling, and more, are built-in features and so are race detection, vetting, and the go generate
tool.
The Go toolchain is a one-stop shop for all development tooling requirements. It integrates seamlessly into your development flow, so you can focus on programming rather than setup.
12. Built-in testing and benchmarking
Testing and benchmarking are built right into Go with the go test command.
Writing unit tests in Go is easy and idiomatic. The testing package provides everything you need for basic tests up to complex mocked objects and code coverage reporting. No need for learning a new domain language: Go tests are written in plain Go.
By making testing ergonomic, Go supports development practices like Test-Driven Design (TDD). And the benchmarking tools allow comparing different versions of your code for performance.
With Go, continuous unit testing quickly becomes second nature to you, leading to more confidence in your code and much fewer regressions.
13. A thriving open-source ecosystem
Go has a thriving open-source ecosystem with high-quality packages for nearly any need.
The rich standard library provides the foundations, but Go's package ecosystem adds incredible value on top.
Packages like Gin or Echo for web frameworks, sqlc, jet, bob, Ent, or GORM for database access, and Go SDKs for countless public APIs give you ready-made building blocks for the task at your hand. Sharing and discovery are easy with the central package repository at pkg.go.dev. And Go's package management handles dependencies seamlessly.
Bottom line: Go's fantastic community and ecosystem make development productive and enjoyable.
14. Backward and forward compatibility
Backward compatibility has always been a top priority for Go.
The language and standard library are carefully evolved between releases. New versions of Go work with older codebases seamlessly in nearly all cases. You can update to the latest Go confident your software will compile and run without issue.
Backward compatibility enables a stable base to build on. Technical debt and rewrite costs are avoided. Compared to other languages, Go takes compatibility seriously to support long-term projects. Knowing your code will continue working with new Go releases is a weight off your shoulders.
And it gets even better. Since Go 1.21, modules can request to be compiled with a particular version of the Go toolchain, and the installed Go command will happily download and use that toolchain. This is a level of backward and forward compatibility other languages can only dream of.
15. Build-time security
Go's toolchain and module system are designed for mitigating supply-chain attacks.
All dependencies of a build are fully determined. No dependency can change unless explicitly updated in the go.mod
file. Moreover, the Go Sum database guarantees that module versions are immutable, making it impossible to inject modified code into an existing version. Finally, Go doesn't allow dependencies to execute code during builds, limiting the attack surface significantly.
Build-time security even applied to building the Go toolchain. Since Go 1.21, every Go toolchain features perfectly reproducible, verifiable builds. The only relevant input for the build process is the source code; no other moving parts are included.
With these measures in place, and considering other security-friendly features of Go such as static linking, focus on clear code, static typing, and a rich standard library that reduces the need for using external modules, Go is an obvious choice for security-aware projects.
Conclusion
It took only three of these properties to have me sold on Go: The clear syntax and semantics, concurrency, and the fast compiler. I quickly learned to know and admire the rest of these properties during my first steps in Go. So even if you can only check off three of these properties as relevant for you, give Go a try.
Banner image: background photo by Alexander Grey on Unsplash, Gopher by me
Updates
- 2025-04-21: Add a paragraph on perfectly reproducible builds. Mention race detection, vetting and code generation. Link to the GC guide. Clarify GC efficiency. Mention zero-alloc techniques. Mention inheritance. Mention fully static, self-contained binaries. Point out that the stdlib is production-ready (which not everyone might take as a given). Link out to the stdlib docs. HT to Redowan Delowar for suggesting improvements.