I’ve got to disagree with this strongly. I built and operated the same large system in both languages (acquisition forced me to rewrite) and both the dev and operating cost of the JVM was much higher.
Go is a high velocity language. Code reviews on language/style issues are non existent, it’s GC is blazing fast (not our experience with JVM) and it’s really easy to read. I’ve watched many new engineers ramp up on both systems, as both operated side by side for a while, Go was inevitably faster for engineers.
Lack of a "default" stack for nearly anything. The stdlib is great but the ecosystem isn't. Which web framework? Does it come with a logger? If not which logger? Do the third party libraries I want to use work with my logger/have a mechanism to provide one via an interface or am I shit out of luck? This goes for so many more things though, cache libraries, data structures (because Go stdlib collections are a joke). Contrast to Java here you have a relatively minimal set of very long-lived deps for all of these "basic" things. Ecosystems like Spring, the slf4 facade, Apache etc provide the foundation that most Java programs sit on and that has no alternative in Go land.
Go module transition was also hot garbage. It's better after sure but going through it was worse than Java 8-9 or to Java 11+ both of which were "difficult" transitions for Java but vastly less disruptive for me personally at least.
Then take all of this stuff and multiply it by the number of teams you have if you don't have a central team doing library choices and laying down architecture guidelines - which we eventually got but not before all the Go codebases had turned into by and large unmaintainable messes.
IMO Go is high velocity only in the simplest sense, it's very easy to pump out shit tons of code. With a big team of mediocre developers this is even more true. The problems all come later. Big change in requirements? Good luck with that.
Had a team try to go crazy functional with Go and now they have immutable data everywhere and allocations are completely destroying the throughput of the Go GC? Good luck fixing that. etc.
The velocity eventually moves from it's strength to it's achilles heel once the codebases are big and bad they are really hard to fix.
I get that most of these problems are "big company" problems and maybe in smaller teams with a stronger hiring bar you won't run into these or maybe not at the same severity but they severely impacted my view of how well the language scales to large teams and codebases.
Teasing this apart I see a few things: a) logging, b) modules rollout and c) missing frameworks.
I’ve never had a logging issue in large systems. Explicit error return (as you know, on every function) allows you to log in your code, not lean on only libraries that support your interface.
Modules rollout was part of growing up. But, you won’t get Go 1->2 upgrade issues as we have 100% backward compatibility on version upgrades. Moving to the latest version of Go is trivial and simply unlocks new features.
Too many allocations for Go is going to be too many allocations for JVM too. This seems like an problem isolated to that team.
I’ve done Go at both a three engineer startup and at Google and I can’t help but notice none of these are really the type of problem that crop up later.
Though I still don't see a standard web stack. "stdlib is enough" is only true for people that don't need their hand held and/or can organise good standards across teams.
If it was just me or people I know are good writing the software that works. At Google it probably works because of aforementioned hiring bar. At the average large-ish company? Not something I like leaving to chance because I have usually ended up disappointed.
Even it's latency is outclassed by ZGC and Shanandoah.
The GC monoculture is great from a simplicity and out of the box experience but there is a very good reason to a) want multiple different GCs tuned for different workload types and b) have competition so that the best designs can be found rather than having to fight to be the only implementation.
Huh, Go also does not allocate ten times more more memory like Java. So even if Go's GC is 1/10th performant as Java (and it isn't) it will be equally better Go applications.
Java's GC improvement is relentless because Java's applications are relentless in memory allocation.
Being on endless Java memory/perf issue prod calls I can say Java GC improvement, performance tuning is cottage industry in itself. Meanwhile end users keep suffering but at least Java devs get to tune GC to their heart's content.
I’d love to see you elaborate on this. Anecdotally, my experience was the exact opposite. Is there some documentation making this point?
In the course of optimizing I came to know the various JVM GC algos (concurrent mark/sweep, parallel old, etc) by the corresponding memory graph alone. I never, ever had to debug similar latency in the Go stack.
Both of those are only picked for low sized heaps with few cores, probably within a container. Were these micro services?
G1 is the default for larger heaps and multiple cores, and ZGC and Shenandoah (low latency GCs) have to be manually turned on AFAIK.
OP said:
>Java doesn’t slow down the allocation rate, it tries to keep up with the churn.
This is incorrect. ZGC will block a thread when it cannot give a thread any memory, because it can't collect and free memory at the pace needed. Google "allocation stall" for this. ZGC can achieve very low latencies akin to Go's GC, I don't know if the throughput is higher or not. Multiple cores and some GiB of heap space is when ZGC will shine.
No web framework, the standard library is enough. log/slog is in the standard library now, and is compatible with zap, which seems to work with everything.
>IMO Go is high velocity only in the simplest sense, it's very easy to pump out shit tons of code. With a big team of mediocre developers this is even more true. The problems all come later. Big change in requirements? Good luck with that. Had a team try to go crazy functional with Go and now they have immutable data everywhere and allocations are completely destroying the throughput of the Go GC? Good luck fixing that. etc.
I doublt things would go better for teams trying to go full OO in haskell, or full functional in Java.
The stdlib really isn't enough unless you want num_teams x session handling implementations etc.
> I doublt things would go better for teams trying to go full OO in haskell, or full functional in Java.
That is the beauty of Java, no one does this.
They don't feel like they need, should or will get approval to.
Go is pretty much the wild west because "the std lib is enough" attitude permeates everything. Build your own datastructures, build your own anything really.
I can understand why many people find that attractive and hate Java as a result, sometimes Java feels more like Lego and less like programming but it does create predictable reliably constructed software that is generally easy to clean up even if it's done a bit poorly.
Which is something I value because I often end up in the code janitor role and/or being air-dropped in to get a project back on schedule or drastically cut down the defects etc.
Go is a high velocity language. Code reviews on language/style issues are non existent, it’s GC is blazing fast (not our experience with JVM) and it’s really easy to read. I’ve watched many new engineers ramp up on both systems, as both operated side by side for a while, Go was inevitably faster for engineers.
What made maintaining Go hard for you?