Why Go Became My Favorite Programming Language
During a migration project I worked on, we had to process a very large number of files.
At first, Node.js felt like the natural choice. It was already part of the ecosystem we were working in, and for many kinds of backend tasks it can be a very productive environment. But as the migration became more file-processing heavy, I started to feel more friction than I expected.
The standard library wasn’t particularly comfortable for this kind of work, and many of the third-party packages I looked at didn’t inspire enough confidence for something as critical as a migration flow.
So I decided to try Python.
On paper, it seemed like the obvious alternative. Python has a strong reputation for scripting and automation tasks, especially when large amounts of data or files are involved.
But the experience turned out to be less straightforward than I expected.
Very quickly, I found myself dealing with questions that were not really part of the problem I was trying to solve.
- Which Python version should I use?
- Which package manager should I rely on?
- Which library was actually the right one?
- What was the cleanest way to structure the environment?
None of these problems were impossible, but even getting to a clean starting point took longer than it should have.
At some point, I decided to give Go a chance.
And that experience surprised me.
What impressed me first wasn’t performance or concurrency, the things people usually mention when talking about Go.
What impressed me was something much simpler.
There was almost no friction.
- I didn’t need external libraries just to get started.
- The setup was simple.
- Compilation was extremely fast.
- Testing didn’t require choosing between multiple frameworks.
It felt like many of the practical decisions had already been made.
That was the moment Go really caught my attention.
Not because it was flashy. But because it quietly removed resistance from the development process.
Over time, that first impression turned into something deeper.
Simplicity that holds up over time
One of the things I appreciate most about Go is its simplicity.
At first, this simplicity can feel restrictive. Developers coming from languages with richer type systems or more expressive abstractions may feel that Go is missing tools.
But over time, especially in larger systems, that simplicity becomes a strength.
Most software problems don’t come from not having enough language features. They come from systems becoming harder to understand, harder to change, and harder to debug as they grow.
In that environment, a language that nudges developers toward clarity becomes extremely valuable.
Go isn’t trying to help you write the most clever code in the room.
It’s trying to help you write code that still makes sense six months later.
An opinionated development environment
Another reason Go stood out to me is that it feels like more than just a programming language.
It feels like an opinionated development environment.
Many ecosystems require developers to make a long list of decisions before they even start writing code:
- Which formatter should we use?
- Which testing framework?
- Which build tool?
- Which dependency management approach?
Go removes a surprising number of these decisions.
- Formatting is handled by
gofmt. - Testing is built into the language via
go test. - Dependency management is handled by
go mod. - Building binaries is straightforward.
This consistency saves time and removes a surprising amount of cognitive overhead.
Instead of assembling a development environment from many moving parts, Go provides a coherent workflow out of the box.
A standard library that feels practical
The standard library was one of the first things that genuinely impressed me.
For many backend problems, it already provides the essentials: HTTP servers, JSON handling, file operations, concurrency primitives, and testing utilities.
This changes how projects begin.
Instead of immediately searching for libraries, you can often just start writing the program.
That makes the development process feel calmer and more focused.
Backward compatibility as a principle
One of the things I respect most about Go is its commitment to backward compatibility.
A programming language is not just syntax. It is a long-term contract with the engineers building systems on top of it.
Teams invest not only code but also tooling, operational knowledge, and development practices into a language.
When that foundation changes too frequently, the cost shows up in migrations, rewrites, and lost engineering time.
Go’s compatibility promise communicates something important:
stability is a feature.
Concurrency that feels native
Concurrency is another area where Go feels very natural.
This doesn’t mean concurrency suddenly becomes easy, it never does, but Go provides a model that feels built into the language instead of layered on top of it.
Goroutines and channels make it easier to structure programs around independent tasks and communication.
For backend services, worker systems, and pipelines, this model fits extremely well.
A pragmatic take on object-oriented design
Go keeps the useful parts of object-oriented programming, such as interfaces and composition, while avoiding heavy class hierarchies and complex inheritance structures.
This encourages a design style that favors smaller abstractions and clearer boundaries.
In practice, that tends to produce systems that age well.
The parts that still frustrate me
Of course, Go is not perfect.
Verbose error handling is probably the most obvious frustration. Explicit error handling improves clarity, but it can also become repetitive in larger functions.
Go’s minimalism can also feel restrictive at times. The same simplicity that keeps systems readable can sometimes limit expressiveness.
Another friction point I experienced is how tightly Go module paths are coupled with repository paths. It’s not a major issue, but it can make early project setup slightly more rigid.
(I plan to write more about that separately.)
Why it still became my favorite
Over time, I realized something had changed in what I value in programming languages.
I care less about clever syntax and more about systems that remain understandable years later.
I care less about elegant tricks and more about software that is easy to run, deploy, and maintain.
Go may not be the most expressive language.
But it consistently helps teams build software that is:
- simple to run
- easy to deploy
- stable in production
And that combination is surprisingly rare.
Go became my favorite language not because it is perfect.
But because it allows me to focus on solving problems instead of fighting the environment around them.
Further Reading
- For a systems-oriented example of where Go fits well in production workflows, read Understanding Docker: Containers, Images, Layers and the System Behind Them.
- For architecture thinking beyond language choice, read Foundry: A Practical Methodology for Turning System Design into Engineering Decisions.