upvote
As a system administrator, I vastly prefer to deploy Go programs over Java programs. Go programs are typically distributed as a single executable file with no reliance on external libraries. I can usually run `./program -h` and it tells me about all the flags.

Java programs rely on the JVM, of which there are many variants. Run time options are often split into multiple XML files -- one file for logging, another to control the number of threads and so on. Checking for the running process using `ps | grep` yields some long line that wraps the terminal window, or doesn't fit neatly into columns shown in `htop` or `btop`.

These complaints are mostly about conventions and idioms, not the languages themselves. I appreciate that the Java ecosystem is extremely powerful and flexible. It is possible to compile Java programs into standalone binaries, though I rarely see these in practice. Containers can mitigate the messiness, and that helps, up until the point when you need to debug some weird runtime issue.

I wouldn't argue that people should stop programming in Java, as there are places where it really is the best choice. For example deep legacy codebases, or where you need the power of the JVM for dynamic runtime performance optimizations.

There are a lot of places where Go is the best choice (eg. simple network services, CLI utilities), and in those cases, please, please deploy simple Go programs. Most of the time, developers will reach for whatever language they're most comfortable with.

What I like most about Go is how convenient it is, by default. This makes a big difference.

reply
Java still had slow startup and warmup time circa 2005-2007, on the order of 1-3 seconds for hello world and quite a bit more for real apps. That is horrendous for anything CLI based.

And you left out classloader/classpath/JAR dependency hell, which was horrid circa late 90s/early 2000s...and I'm guessing was still a struggle when Go really started development. Especially at Google's scale.

Don't get me wrong, Java has come a long way and is a fine language and the JVM is fantastic. But the java of 2025 is not the same as mid-to-late 2000s.

reply
Maybe so, although I don't recall it being that bad.

But Go wasn't designed for CLI apps. It was designed for writing highly multi-threaded servers at Google, according to the designers, hence the focus on features like goroutines. And in that context startup time just doesn't matter. Startup time of servers at Google was (in that era) dominated by cluster scheduling, connecting to backends, loading reference data and so on. Nothing that a change in programming language would have fixed.

Google didn't use classloader based frameworks so that also wasn't relevant.

reply
Golang is frequently used for CLIs, even if it wasn't designed for that exactly
reply
If you want to write CLI tool, you use Rust.
reply
Or you use Golang? A lot of the time there isn't a big difference.
reply
Who said that? Go is pretty amazing to whip up great CLIs quickly.
reply
deleted
reply
Not when using commercial JDKs, but naturally most HNers never worked on companies that paid for those.

For example initial JIT caching experiments on OpenJDK came from J/Rockit.

reply
Java absolutely does not fill in the niche that Go targeted. Even without OO theology, JVM applications are heavy and memory intensive. Plus the startup time of the VM alone is a show stopper for the type of work I do. Also yes, Java isn’t hip and you couldn’t pay me to write it anymore.
reply
The old OOP testament was written by Smalltalk and C++ apostles, then the school of Objective-C belivers was found, and some of the scholars helped with the new Java religion.
reply
Golang having solid n:m greenthreading day 1 was its big deal. Java has had no good way to do IO-heavy multitasking, leading to all those async/promise frameworks that jack up your code. I cannot even read the Java code we have at work. Java recently got virtual threads, but even if that fixes the problem, it'll be a while before things change to that. Python had the same problem before asyncio. This isn't even a niche thing, your typical web backend needs cooperative multitasking.

I'm also not fond of any of the Golang syntax, especially not having exceptions. Or if you want explicit errors, fine, at least provide nice unwrap syntax like Rust does.

reply
by FAR my biggest complaint about Golang was null instead of Option. could have been special cased like their slice and map and would have been so so so much better than nil checks imho. really, a big miss.
reply
Java 21 has n:m green threads, but with caveats. Java 24 removed a major source of the caveats.
reply
I'm sure you're already aware but for those who aren't - Java 21 was released in 2023. Golang 1.0 was released in 2012.
reply
In 2012 we could do much of the same stuff with Java 5 concurrency framework and futures (aka promises everyone raves about on JS land), with the advance that scheduling can be customised.
reply
That's what I meant by unreadable code. You have to twist everything to work with whatever async framework.
reply
Have you ever had to write down channel sending dependencies graph?

I had to, to make sense of whatever was going on.

reply
If this is an app backend, you aren't dealing with Golang channels directly. Your webserver or whatever it is spawns a new goroutine (greenthread) for each incoming request, then you use blocking calls without worrying. Looks similar in JS but the event loop handles it instead, and you async/await stuff. JS webpages and app frontends also don't worry about this.

If this is systems programming, yeah you're reasoning about channels, but that's mostly the same in any language. Golang has slightly nicer support for that if anything.

reply
Yeah, I'm hoping that fixes things eventually. We still can't use that at work, and even once we can, there's 10yo code still using 3 different old ways of async.
reply
"it picked up its users mostly from the Python/Ruby/JS world rather than C/C++/Java"

And with the increasing performance of Bun, it seems that Go is about to get a whooping by JS.

(Which isn't really true, as most of the Bun perf comes from Zig, but they are targeting JS Devs.)

reply
Runtimes like Bun, Deno, or type systems like TypeScript don’t change the fact it’s still JS underneath — a crappily designed language that should’ve never left throwable frontend code.

None of these runtimes make JS anywhere even close to single-threaded Go perf, let alone multithreaded (goroutine) perf.

reply
JS is perfectly designed for what it does, frontend and non-CPU-intensive backend code. It's never going to reach singlethreaded Golang perf.
reply
JavaScript was never designed for non-browser usage. It’s the community’s unquenchable thirst to use the same language everywhere that brought us here.
reply
NodeJS about page makes its case pretty succinctly, JS was a good fit for IO-bound concurrent backends because of the event loop. This was at a time when no other major language/runtime had a good answer for this unless you count Erlang. Plenty of people using it didn't even come from the web frontend side, myself included.

npm was also maybe the first default package manager that "just works," unlike Python or browser JS.

reply
A lot of people don't realize NodeJS was made because the creator wanted to make a runtime dedicated to asynchronous IO, didn't want to use a language with a pre-existing standard library and ecosystem built around synchronous IO, and realized that JS almost uniquely fit the bill. It was not built for the purpose of letting people who only knew JS use JS on the server.
reply
This tracks, cause the NodeJS website also doesn't mention anything about people already knowing JS. And imports worked completely differently between browser and Node, so they were pretty separate things at least at the start.
reply