I’ve been using Golang professionally for a number of years now, having had my first exposure in 2017 or maybe 2018. It was sold to our team as a faster version of Java, with a lot of cleaner libraries that would help us write, build and deploy much faster than our existing Java application.
For the most part, I’ve not only found that to be true but to have completely altered some of my existing ideas on software engineering.
You ain’t gonna need it is a common refrain in software engineering, but it’s a common trap that I’ve seen others (and myself) fall into.
As an example, when I first picked up Go, I immediately thought “well, the built in library is probably bare bones, better look for a framework”. Little did I realise how extensive the core library actually is.
Most of the bread and butter type scenarios are covered quite nicely by the core library, and when it doesn’t cover whatever you’re doing it does force you to step back and ask yourself whether it’s actually necessary. I haven’t used any DI frameworks or ORMs since I last used Spring with Java, and honestly I don’t miss them.
Magic is Evil
Speaking of dependency injection, I used to think it was really cool how I could configure things at runtime and inject only the code I need. How many times have I used this feature of DI production systems? Once, and, thinking back on it, I don’t think it was necessary.
It’s not common (unless you’re distributing code to clients) that you’ll need to support multiple databases, change out interface implementations or even have to wrap things outside your dev environment.
Go favours the explicit over the implicit. A good Go app will have all the wiring
code at the top, and everything will be completely transparent. There will be no
@Inject madness that will cause your stack traces to blow out to 300-400 lines,
there won’t be any generated SQL queries, you control your implementations and interceptors
and it will be obvious what is doing what.
It was a little jarring at first, but now I have no idea how I developed an almost Stockholm Syndrome-like attachment to one of Spring’s core features.
Generated Code is just more Go
I remember when using Spring, you’d have to configure Maven or Gradle processors to get some of the more generative type features. I did a few interceptor type classes that’d get wired up using various annotations, and Spring Data queries weren’t always obvious.
When I use Go, it’s completely normal to generate certain plumbing, but I can still
debug problems because it will end up in my go project (usually in
/gen) as normal
go code, tying back into the anti-magic stance of much of the go community above.
Tooling shouldn’t be an optional feature
Java is a bit of a trash language on its own, but the reason in maintains a lot of its dominance is the well supported ecosystem of 3rd party tooling. Maven, Gradle, and performance and testing tools are all examples of a community supported effort.
These are all 1st party things provided by the Go project. Module resolution is kind of
recent (previously handled by
dep), but the
testing package and
pprof came about in
2014 according to the git commit history. The tools mentioned are actively maintained and
are more than enough for a cheapskate like me.
Not sure whether this is just because Go is a younger language, or whether companies like Oracle just don’t care to support these things, but I’m now of the belief that there should be basic tools for at least performance and dependency management included with every modern language.
Go is a great general purpose language, but I think the way it’s forced me to reevaluate my thinking has been one of the best things it’s given me. A lot of my code has been simpler, easier to read, and easier to communicate to my coworkers.