4 ms·
In my experience, Go appears simple as long as you’re solving simple tasks. Once you need to model fairly complex semantics, whose structure and detail depend o
by jmaker 2y ago
In my experience, Go appears simple as long as you’re solving simple tasks. Once you need to model fairly complex semantics, whose structure and detail depend on your business domain, Go code turns illegible, with lots of hackily lumped together bloated nonsensical channels and for-selects stemming from async IO and multi-threading forced into the goroutines syntax, with hard to formulate structured concurrency. And then you bolt on your validation logic on top of it, with several Go idiosyncrasies, and then you need to explain the distinct consumer-side interfaces, underwhelming generics and myriads of conventions based rules. One could claim that’s not how one writes “good” Go code. But that’s what depends on the complexity and dynamism of your domain logic and the folks you work with. After Java, production grade Go for larger projects is terrible. Null pointer method receivers, interface reification. And now the experiment with the functorial ranges, increasingly with more and more genetics, all without any syntactic sugar… hard to read, hard to explain.
Oh and the GC is rather inefficient compared to most JDK distributions. Compared to modern Java or Kotlin, for my project requirements, I don’t want to do as much Go as I used to. JDK Mission Control and Flight Recorder alone with great IDEs and profilers are golden. And you pay in RAM for JDK apps.
As for Rust, it just requires more upfront cost, but makes you consider potential failures at every step. Debugging production code isn’t fun, fuzz tests aren’t enough to assure quality to the extent Rust’s type system can. I trust rustc much more than I trust myself or other devs. If the code passes rustc, and the type semantics are correct, I’m 3/4 certain the code is correct, that’s a very high watermark, albeit at the cost of the upfront effort to satisfy the type constraints. Much more efficient in terms of dev time than debugging Python or Go at runtime.
Anyway, one can easily run many Python packages on GraalVM Truffle for direct interfacing with Java, Ruby, R, and via PyO3 with Rust, for which you have the native Polars data frame library, which all cover a good chunk of Python programs. Rust also teaches one to do proper ownership accounting for the variable bindings, great for C++ devs and for heap escape analysis by inspection for Go devs alike. Lots of Go bugs result from lack of understanding of ownership and implicit reference binding as opposed to copy and move semantics. Some of that was now “improved” with Go 1.22 for closures in loops.
- neonsunset 2y agoOr you could just use .NET instead and get both expressiveness and first-class concurrency primitives with none of the Go’s warts.
- kjeetgill 2y agoNot OP but between Java and C# it's hard to not to lean Java for the absolutely massive lead in high quality libraries and ecosystem support. C# still feels like the new kid in open source circles though the languages are 90% the same.
- neonsunset 2y agoThis kind of response is a common issue .NET has to deal with. C# is not Java, I wish it was tongue in cheek but I keep having to seriously respond to these, as unfortunate as it is. First OSS version of .NET was released 8 years ago. Java is much higher level and much more OOP focused language than C# of today, which is multi-paradigm and exposes a lot of low-level features when needed, and is implemented under the hood way closer to the likes of C++ and Rust. The difference in quality is dependent on the context. If a company is a pure Java shop that lives and breathes Apache projects - sure. Not so much or opposite otherwise.
- jayd16 2y agoWhats a good example of a library that Java has that's missing in .NET? I really can't say I've ever had to worry about library support in C#.