Live data from Hacker News

One year after switching from Java to Go

glasskube.dev

211–220 of 503 posts

Re: One year after switching from Java to Go

#211

Going back to first principles, nominal typing is what I miss most with Go. I get the utility of structs + interfaces + structural typing, but most of the time there is more benefit in declaring that a type nominally implements an interface when that is the intention. Code is far easier to read and understand that way, both for developers and tooling. I suppose exclusively structural typing would be more acceptable i…

[deleted]

Re: One year after switching from Java to Go

#212

The jvm is a pretty insane beast. It will do usage based recompilation, escape analysis for memory, so non heap allocation is super fast, has great memory safety... But a lot of people use it with spring/spring boot, a technology designed to work around the complexities of a particular type of middleware software in the late 90s and early 2000s. It's cargo cult programming of the highest order. In the OP, the author…

> But a lot of people use it with spring/spring boot, a technology designed to work around the complexities of a particular type of middleware... No, people use it because we don't want to reinvent the wheel. Spring is well documented and Spring Boot gives you a set of dependencies that all work together. Then you don't have to spend time messing around with things like OAuth and authentication, you can just write th…

> Then you don't have to spend time messing around with things like OAuth and authentication, you can just write the application.

It sounds good but in reality people end up spending time messing around with config files and annotations.

Re: One year after switching from Java to Go

#213

The jvm is a pretty insane beast. It will do usage based recompilation, escape analysis for memory, so non heap allocation is super fast, has great memory safety... But a lot of people use it with spring/spring boot, a technology designed to work around the complexities of a particular type of middleware software in the late 90s and early 2000s. It's cargo cult programming of the highest order. In the OP, the author…

Yep.

Java is really good. Java developer culture is awful.

If you instead of spring boot just pick a few dependencies you really need, you don't throw the whole Design Patterns book at it just because you can, and you don't try to make everything changeable without recompiling or redeploying, it's pretty nice to work with

Re: One year after switching from Java to Go

#214

I work with a brownfield go monorepo with a couple different styles and lesser known “frameworks” in it. It sucks to work in, one of the previous devs was a huge fan of clean code, so every function with more than a couple inputs has its own struct, pointers are used everywhere just by default (and basically never nil checked) and the AI generated tests are so plentiful that changing a small thing quickly explodes in…

Disasters can be created in any language, right? Has little to do with Go.

True, but most of the arguments against java in this thread are similarly about bad dev practices and not the language itself.

Re: One year after switching from Java to Go

#215

Going back to first principles, nominal typing is what I miss most with Go. I get the utility of structs + interfaces + structural typing, but most of the time there is more benefit in declaring that a type nominally implements an interface when that is the intention. Code is far easier to read and understand that way, both for developers and tooling. I suppose exclusively structural typing would be more acceptable i…

While having to declare the interfaces a type implements can increase the readability, it comes with a huge drawback: you are limited to implementing the interfaces considered when writing the code. In my eyes it is a fascinating and important feature that you can add interfaces and all existing types automatically implement them, if they, by their methods signature, implement them. You don't have to edit their type declarations to do that.

Re: One year after switching from Java to Go

#216

Earlier quoted context omitted.

To each their own. I'm not going to claim to be an expert, but as somebody who's been coding since the 80s it was a breath of fresh air to see Go do what I wanted languages to do all long instead of ramming exceptions down my throat. I have problems with Go (examples: slice behavior and nil type interfaces) but error handling is not one of them.

What challenge did you run into with exception handling? I'm curious because I've never felt it being onerous nor felt like there was much friction. Perhaps because I've primarily built web applications and web APIs, it's very common to simply let the exception bubble up to global middleware and handle it at a single point (log, wrap/transform). Then most of the code doesn't really care about exceptions. The only cas…

Having exceptions means that every line in your function is a potential exit point, often without you being aware of it. This can lead to bugs when a non-atomic operation is abruptly terminated, and you might not realize it just by glancing at the code.

When we were rewriting some code from PHP to Go, I remember that simply thinking about "what to do with err" led me to realize we had a ticking time bomb - one that could explode in production. We had never realized that a certain line of PHP code could potentially throw an exception, and letting it bubble up the stack would have resulted in data corruption. With Go's explicit error handling, this issue became immediately obvious.

Re: One year after switching from Java to Go

#217
post #66

Earlier quoted context omitted.

I’m also a long time java spring developer. I started writing a game recently and was really surprised about how bad the performance can be when you run it in a tight game loop. The startup time is also a real problem, as you really want to be able to scale up pods quickly. That said, it’s good enough right now. You can make it work at scale, and it’s worth the cost trade off of trying to do it more efficiently in a…

Most "microservice" backend type stuff is I/O bound, not CPU bound. You're likely not going to win much. Maybe get away with lower memory instances though.

Cold latency is an issue with microservices. If you need to use Java, you'll likely end up using frameworks like Spring or Quarkus, which somewhat diminish the advantages of using the JVM and Java as a language.

At that point, you might as well start with Go from the beginning.

Re: One year after switching from Java to Go

#218
post #7

I’ve been out of the Java scene for a really long time, but will be coming back to it soon. I’m curious - these performance issues described here, are they inherit to how Java itself? Is it baggage from Spring/Boot? Are there ways to get more bang for the buck with some careful choices in a system like this? The closest I’ve done to Java recently is C#, which I think may have similar challenges, but overall didn’t se…

My experience with very simple Jersey web apps is ~1.5 seconds to start up. Much less than his reported ~8 seconds with Spring Boot, but still not in the 100 ms range he reports with Go. I assume one second or so is about as low as you can go with a mainstream Java framework without AOT, though I'd be happy to be corrected.

Also, you don't have to continuously restart the server for every change. Can hot swap code. And for tests there are solutions to keep the jvm running between the code->test->fix cycle. But I've never felt the need for those, running a single test is often plenty fast as one doesn't need to instantiate the whole app, only the dependencies needed for the test. So plenty fast.

Re: One year after switching from Java to Go

#219

The jvm is a pretty insane beast. It will do usage based recompilation, escape analysis for memory, so non heap allocation is super fast, has great memory safety... But a lot of people use it with spring/spring boot, a technology designed to work around the complexities of a particular type of middleware software in the late 90s and early 2000s. It's cargo cult programming of the highest order. In the OP, the author…

> But a lot of people use it with spring/spring boot, a technology designed to work around the complexities of a particular type of middleware... No, people use it because we don't want to reinvent the wheel. Spring is well documented and Spring Boot gives you a set of dependencies that all work together. Then you don't have to spend time messing around with things like OAuth and authentication, you can just write th…

> Spring Boot gives you a set of dependencies that all work together.

But spring boot deps is infamous meme.

> Then you don't have to spend time messing around with things like OAuth and authentication

Yeah. The funny thing is reality is quite complicated and spring supports a lot of (almost) documented cases. But 99% javaspring developers do not care. I met quite a lot of experienced devs and only 2 of them know how to optimize application start or which errors Kafka wrapper would not retry and so on. Half of the non-default situations are solved via reinventing the wheel because of a lack of understanding of nuances. I can't say people are dumb, many of those devs are smart. I tend to say that ultra-framework kills people's expertise and in the long term hardly saves resources.

Re: One year after switching from Java to Go

#220
post #117

Earlier quoted context omitted.

What challenge did you run into with exception handling? I'm curious because I've never felt it being onerous nor felt like there was much friction. Perhaps because I've primarily built web applications and web APIs, it's very common to simply let the exception bubble up to global middleware and handle it at a single point (log, wrap/transform). Then most of the code doesn't really care about exceptions. The only cas…

Exceptions are fine if you never catch them. So is calling abort(). (Which is the Unix way to do what you described.) If you need to handle errors, you quickly get into extremely complicated control flow that you now have to test: // all functions can throw, return nil or not. // All require cleanup. try { a = f(); b = a.g(); } catch(e) { c = h(); } finally { if a cleanup_a() // can throw if b cleanup_b() // null che…

> So is calling abort(). (Which is the Unix way to do what you described.

But in gui applications and servers, you will need to catch and report the error in some intermediate boundary, not exit the application. That's where go falls short.

Post reply on HN