Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I don't think any existing Go developer is going back to Java.

I worked with Java for 10 years and switched to Go and I will never go back.

This is mostly because applications and libraries are so hard to reason about and understand due to inheritance, packaging, OOP, build tools ect compared to Go.

Go is simple. It's easy to understand, read, and maintain. The packaging is like how you would package files on your computer in single folders. The tooling is built into the language. You don't need a IDE like IntelliJ just to make it feel reasonable to work with.

Maybe all of this has changed, but most of the libraries I see in Java today still look like this.



> This is mostly because applications and libraries are so hard to reason about and understand due to inheritance, packaging, OOP, build tools ect compared to Go.

You are just at the early phase of the project.

> Go is simple. It's easy to understand, read, and maintain

My opinion is that Go is too simple, to the point that it hinders understanding and readability. 4 nested loops with random mutability is much worse than a clear Stream api "pipeline". The 31st if err check will not be actually handling the underlying problem, while you can't forget about Exceptions -- even if they do bubble up to the main app, you will clearly get an actionable stacktrace.

> The tooling is built into the language

This has benefits, I will give you that. At the same time, I think all these new build tools are anemic and can't be used for anything more complex than interacting with the same language's standard dependencies. Gradle is not sexy, but is actually capable of doing any kind of build.


Im convinced Go is just an incomplete language masquerading as a simple one.


Go is a complete and simple language, and this is a fairly objective claim.

Unless by "incomplete" you mean it could have more features. But C++ and Rust (and Java) have been piling on features for years, with no signs that they will ever slow down or stop, proving that they're also "incomplete" by this definition. IMO this is really just a result of there being too many cooks in the kitchen, and a lack of leadership committed to saying "no" to feature requests.

This is also why using Rust or C++ requires every organization to agree on a subset of the language they will utilize. Rust isn't as far along this path, but it's heading in the same direction as C++.

But with Go, every organization can use the complete language. That's how simple it is.

Go has been used by many organizations to build stable, large, and scalable systems that have been operating successfully in production for many years now. That's how complete it is.


I wonder if replacing the type system in Go with the one in Rust and adding native Actor model support would be doable. Or if GC and compile time would regress too much. Modern languages without good sum types just seems like such a lost opportunity to me.


What would be the point? Why stick with Go if you want so deep-reaching changes?


That what I often wonder, if one is going to start using a new language why go? Rust at least it gave one memory safety and not having to use GC make it more stable usage of resource as the discord article have already pointed out. Seem like go is just google's .NET, every big corp need to have their own language.


>>You are just at the early phase of the project.

Nah.

99% of the code written out there doesn't need layers of indirection, responsibility tossing around, Code splitting across classes, design patterns, inheritance and the class jungle that is common in Java.

Rise of languages like Go is simply majority of the people realising when they want X, they are better of writing just X. You don't have to write a generic version of X that needs to work in a dozen situations. This is for a simple reason. Most of the times, there are no dozen situations. Most, not all the times.

Most of the code I write, doesn't change all that much. If you are writing code that needs to run for decades in an industry where grifting and job hunting is a daily affair you are doing it wrong.


> Most of the times, there are no dozen situations.

After 20 years of building all sorts of software, I know that this a fact, but the challenge is to make others aware of it.


> You are just at the early phase of the project.

Lately, I am seeing very few codebases getting supported more than 3 years in companies offering software products. Every 2-4 years services are getting rewritten, what's the point of having tool intended for 15 years, when services are deprecated in 4 years


It would be good for my job if learned go, but I've been having a hard time because it's just so boring.


You're doing it wrong if you think programming for work is about the code being a means of expressing your inner soul. The most successful professional programmers derive their enjoyment from achieving business objectives, like making products that users love and improve the world.

If you want to express your soul in your code, do that on the weekend using whatever language you want. Trying to mix these motivations is a recipe for disaster.


> The most successful professional programmers derive their enjoyment from achieving business objectives, like making products that users love and improve the world.

Successful by what metric? Achieving business objectives? I don't necessarily disagree with the point, but this seems like a truism.


Or a tautology. No true professional programmer would derive more enjoyment from beauty than from making his boss happy.


I have too much skepticism of "businesses objectives" to be especially interested in success. I want something that'll bend my mind.


Honestly, just find yourself a project and just Go for it (sorry for the pun).

The syntax is easy enough you can start coding just after having looked at basic examples.

Personally I actually like Go because it's so boring.

I tend to see languages more like tools rather than valuable knowledge I must learn, so a simple yet powerful enough language is a perfect fit for me.


I did. Did Go professionally for ~5 years and went to JVM.

Go is easy, but it's surface level easy. Building and maintaining large applications in Go if you don't have a huge team is a giant pain.

JVM (especially paired with Kotlin) for me atleast has meant regaining the expressivity I was missing from Ruby and Python when I moved to Go whilst retaining (well actually usually beating) it on performance and scalability.

I lost absolutely nothing to go to JVM but gained so many things.


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.

What made maintaining Go hard for you?


The main pain-points in a large org at least:

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.


Good to hear logging has gotten better.

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.


> Too many allocations for Go is going to be too many allocations for JVM too

No, Go’s GC is a toy compared to the JVM’s. It is lowerish in latency by actually stopping the application threads when under high contention.

Java doesn’t slow down the allocation rate, it tries to keep up with the churn.


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.


>> (concurrent mark/sweep, parallel old, etc)

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.


> JVM (especially paired with Kotlin)

I agree the Go lang compiler/runtime needs "a Kotlin", with more null-safey build in, proper sum types, a std lib that makes heavy use of null-safety and sum types, better story for polymorphism, better ergonomics for writing stream pipelines, and additional compilation targets (like JS, WASM). This all while proving stellar interop with all Go code, obviously.

Kotlin is quite a sweet deal.


Curious to understand what you are suggesting here. What’s a better story for polymorphism than duck typing? What would (better?) null-safety look like in Go?


I'm saying that we need an XYZ to Go what Kotlin is to Java. The I name some ways that Kotlin improved upon Java that Go would also benefit from.

> What’s a better story for polymorphism than duck typing?

Something that give compiletime guarantees and has not runtime overhead.

> What would (better?) null-safety look like in Go?

https://kotlinlang.org/docs/java-to-kotlin-nullability-guide...


Going on 12 years with Go and agree with everything.


Go's major selling point to me is that you can ship one binary, nothing beats that.

Python, Node, Java all have to pre-install lots of dependencies before you can use them, fine for developers, not so great if you want to distribute software for people who are not software savvy, who typically just wants to download one file, install and start using it.

c and c++ can also do one executable, but, it is not as portable as Golang, and not as static-link friendly as Golang.


> Go's major selling point to me is that you can ship one binary, nothing beats that.

You can ship one compiled binary in Java too if you want it. https://www.graalvm.org/22.0/reference-manual/native-image/

> Go is simple. It's easy to understand, read, and maintain

Go involves a lot of code repetition which makes it difficult to human-scan and maintain. Worked on both large scale Go and Java projects and I found Java projects easier and more comfortable to maintain. Had to pay a lot more attention to Go. Go is easier to write though thanks to its well-designed and extensive standard library which is possibly the best in the world, but the maintenance angle still tilts to Java. There are also more Gotchas in Go compared to Java.


I’m neither a Golang nor a Java developer per se, but I touch source from both as an SRE. I find it weird to see so many comments saying Go is verbose and Java is not. I found the opposite to be true. To do every little thing, the Java code has a ton of abstraction, and the actual implementation of anything is so far removed from the place where it is used that it gives me such a headache to touch anything without wondering “whatever else would break if I change this behavior?!”

However, the Go code bases I’ve encountered have been less abstract and to the point(even if it means repetition of some little things). I also found it to be free of boilerplate except for the if err != nil part.

I guess those that have spent decades in such abstractions must have learnt a skill to navigate such a spaghetti. But, I still hate it every time.


Quite a bit depends on how the codebase has been written and what era are you looking. Before Java 8/9 or after it. Java code written in the recent era is pretty lean and mean.

No matter the amount of abstraction though, one rarely runs into the sort of issues in Java that Go code tend to run into frequently - causing multi-million dollar mistakes frequently even for experienced Go programmers. For loop semantics https://bugzilla.mozilla.org/show_bug.cgi?id=1619047, Unintended variable shadowing, common mistakes in slice appends/copies, slices and memory leaks, defers inside loops, nil interface vs nil, panics in go-routines. There are loads of bugs in OSS projects wrt to these usually repeated again and again.

Go is very simple to learn and very hard to master writing bug-free code. Looking forward to seeing how languages like Rust perform if/when adopted by enterprise.


> You can ship one compiled binary in Java

Even if you’re shipping a jar. You can ship one artifact by using jlink or you ship the runtime in the docker image.

This has been a solved issue for ages.


> not so great if you want to distribute software for people who are not software savvy, who typically just wants to download one file, install and start using it.

i think it's a flaw that wasn't considered properly in the standard java toolchain to not produce an embedded java runtime into a final packaged artifact that is self-executable.

You end up with third party tooling like: https://www.ej-technologies.com/resources/install4j/help/doc... (and https://launch4j.sourceforge.net/ too).

If oracle bundled this tool into the JDK, it would've not been an issue at all.


It has existed for 20 years, and already started with Sun.

Having AOT compilers as commercial offerings, was seen as one way to capture value in the Java market, in a culture where most compilers were still commercial, GCC being the exception.


>It has existed for 20 years, and already started with Sun.

In an anemic way, with mostly third party offerings few people know or care about, and various degrees of pain and shortcoming to their use. It should be a first class feature, and as simple to use as is in Go (including for cross compiling).

In general, if something exists in "some form" for 30+ years in a language, and only a handful of people use it, whereas in another it's used all the time and people from other languages are jealous of how well it works, then the formers "some form" is not a good one.


Regardless, it exists.


There is jpackage and jlink, which don't do single files but make single directory apps.

These days there's also GraalVM native image which does produce Go-like results. But with everyone using Docker on the server anyway it doesn't matter anymore. People who talk about single binaries are confusing to me. What are you doing where shipping one file is so much simpler than shipping a container?


> What are you doing where shipping one file is so much simpler than shipping a container?

Desktop applications.

Java would be a more popular desktop application platform if it weren't for the difficulty in this area (which, to be fair, isn't the only difficulty - cross platform is difficult inherently).


it's pretty hard for average Joe to install a docker engine before he can pull and run dockers, plus docker is not that great for cross platform desktop GUIs.


> everyone using Docker

Not really.


That wasn't a flaw. It was a "feature". Can yo you think of a way to increase market awareness of Java other than putting an icon on every computer in the world saying "Your Java needs to be updated" every two weeks?


jpackage and jlink are shipped in the jdk.


Fully compiled languages have another huge advantage. If you write a tool in Python and targeted say Python 3.10 then people using Phython 3.9 might not be able to use it. So, you really can't use latest and greatest features of Python 3.11 or 3.12. However, with Go, you can build your tool in Go 1.21 or whatever, and the user does not even need a Go toolchain on their machine.

I was planning to write a small side-project to generate GitHub Actions boilerplate. And this time, I intentionally chose Go for that exact reason. https://github.com/ashishb/gabo


Unless dynamic linking is used, or OS APIs change between version, or specific OS files change location.


Go binaries are traditionally statically compiled.


Hence my 2nd and 3rd points.

Also DNS uses dynamic linking unless configured otherwise, while being OS specific, then that are the libraries that rely on cgo.


Yeah, you can list 100 such cases.

Let me tell you the most common scenario. I have a fairly popular FOSS CLI tool written in Python. I cannot use the features from the latest version of Python or else I will alienate ~50% of the userbase. This problem does not exist with Rust or Go.

This problem would have existed for Java on Android except Google took the burden of "desugaring" the Java 17 code -> Java 8 compatible bytecode for the old devices.


Google dug their own grave here, Java is as backwards and forward compatible as it gets.


You cannot run Java 17 code on a Java 8 runtime without "desugaring."


I never see Dart talked about in these contexts but just to highlight a few things.

1. Compiles to native code with a single and very reasonable sized binary on pretty much any platform.

2. Compile to WASM (coming this year) if that’s your thing.

3. Excellent concurrency support with lightweight and simple mental models

4. Variables are not nullable by default thus simplifying tedious checking in your codebase.

5. Syntactically it’s the best parts of Java and JavaScript combined without all the foot guns and verbosity.

6. Full support for both OOP and functional code styles

7. Existing interop support with C, C++, Rust, Java and JavaScript and in the future WASI.

8. Fully static / compile time metaprogramming capabilities coming this year.

9. Also have maybe one of the best teams working on it that I’ve ever seen in an open source project anywhere. They put in a stupid amount of detail and care to try and keep everything pointing in the right direction at a macro level and have really strong levels of transparency around how the language is developed https://github.com/dart-lang/language

Honestly I think it’s critically under-rated and under-used. Most of its common criticisms I see about it are many years out of date.


Combining the best parts of Java and JavaScript isn't exactly something to boast about. Dart lives and dies with the Flutter framework. Other than that it's not doing anything special. Not terrible but also not a significant improvement.


I mean you’ve taken my point, cut it in half to remove the relevant context and are now arguing against a point you’ve made up as some kind of gotcha… I don’t know what you want me to say to that.

Same with your second point. I made a big point to explicitly say I think that right now Dart is very underused and has a huge potential outside of Flutter. Quoting that back to me as though it was something I hadn’t considered is equally as confusing.


I'm with you, I think that Dart is very sensible and very underappreciated language. But he does have a point in saying that currently Dart is tied to Flutter. Google is presenting Dart as a language that you write Flutter with, not as a separate entity. I'd much prefer if Google would present Flutter as a GUI framework for Dart, but alas. Perception is everything. As much as I'd love to start my next project in Dart I probably won't because I can't be sure that Dart won't end up in Google's graveyard in next couple of years whereas I'm pretty sure that Go won't.


I support that. I tried Flutter a few years ago, and I liked Dart and the Flutter way of defining the UI (compared to the old xml stuff in Android).

Then I moved to Kotlin + Jetpack Compose, and I don't see the point of Dart anymore.


You say Dart is underused, but why build something new with Dart when you could do the same thing with a better language? The only reason to use it is Flutter.


Familiarity comes to mind. Dart has developed into a nice direction with sound null-safety, extension functions, sealed classes and compilation to native&wasm. (The libaries weren't very mature when I used Dart, not sure if that changed.) I'd pick Kotlin because I'm familiar with it, but if mdhb is familar with Dart, maybe from his work with flutter, maybe from a time where you'd mostly use Dart to compile it to js, then go for it. Dart is a nice enough language to earn my thumbs up. (not that that would be important to anyone.)


Performance matters. Dart isn't even in the same league.

And its null handling and checking is the worst.

I absolutely hate it. Java over Dart any day.


Dart has excellent null handling[0] so I am not sure if you're perhaps talking of another language? It has had this since release 3.0, if I recall, and has been out for quite a while.

https://dart.dev/null-safety


What specifically about the null checking are you talking about?

I’ve never heard this criticism before and have no idea what you’re even referring to here but I am genuinely curious..


you still need wrap in Dart's runtime though, just like Rust, it's possible to pull in the libraries, it's just not static-link "friendly".


Since Java 9, developers can use jlink to provide a pre-packaged runtime environment bundled with the application. It's not static-link friendly or a single executable, but it does not require the user to pre-install anything or pull dependencies at runtime.


You mentioned "distribute software" but did not consider Electron for Node.

You can make an Electron app with JavaScript and ship the binary (or installer) on any platform. It's not a single executable file, but the user experience is the same.

I don't think there's an equivalent in Go that allows you build a desktop app like that (with frontend and backend both written in Go)?


You can do that with Java too. The JDK has jpackage, but if you want something better than I'm willing to sell that to you (or give it for free, if you're open source):

https://conveyor.hydraulic.dev/

It can be used to ship servers, we use it that way for our own servers. It sets up systemd so you don't need to use Docker. But where it shines is desktop apps.

Windows users get a little 400kb EXE that installs/updates your app and then immediately starts it without user interaction required, so it's effectively a single EXE. Mac users get a bundle. Linux, well, Linux users get a deb that sets up the app+its apt repo, or a tarball. Maybe in future a FlatPak or Snap or something else.

It knows how to bundle and minimize a JDK along with your app as part of the release process. Works great for desktop apps.

It's for Electron too, same deal, easier than Forge in my humble and very biased opinion.


Java GUI is less appealing though


That was true in 2005. Modern Java UI can look pretty great. Two examples:

1. Start IntelliJ and check it out. It's Swing but it feels modern and fresh.

2. Go to https://www.jfx-central.com/ ... JavaFX was introduced years ago to add far better support for modern visuals. JFX Central is a website written with JavaFX itself - it runs server side and streams drawing instructions to the client (implemented using a mix of divs, svg tags and css). You can do this because JavaFX implements the CSS2 drawing model. The website looks modern, like any slick website would today, but you can also download and run it locally. It uses Conveyor to do that in fact. The desktop version looks exactly the same as the web version.


how is jfx-central different from https://openjfx.io?


Different websites run by different people, I think. The former is more of a news site.

But yeah, arguably they should be unified.


but it would still be bettter and more performant than electron based apps.

a little memory heavy, but no more than electron apps while being less janky


For me I use neither, I actually picked wxWidgets after all those desktop GUI troubles over the years, not ideal, but it's the best I found for myself.


> You mentioned "distribute software" but did not consider Electron for Node.

Sorry for the snark, but users will undoubtedly be very grateful to them for not considering Electron.


I'm not so sure if the users of VS Code, Discord, Slack, etc would agree.

Yes it's bulky and sometimes slow, but it offers a lot of features and allow developers to ship features and updates really fast, while only needing one codebase for all platform.


I'm a user of VS Code and Slack and I'd be very happy if they didn't use Electron.

>Yes it's bulky and sometimes slow, but it offers a lot of features and allow developers to ship features and updates really fast, while only needing one codebase for all platform.

Like Slack having 1000x the memory and CPU use for 1/10th of the features a 200K app like ICQ used to have 25 years ago?


I feel vscode is quite good at hiding the fact it's not native, and felt quite snappy when I used it. Slack on the other hand feels painful slow and heavy (and very sensitive to network events like change of network or short disconnections, while native apps are generally much better add handling such glitches for some reasons)


I can't see users caring about it all being one single codebase and I don't think that they should. Every cross-platform development tool like this means awkward, non-native UIs. Maybe there's something to new feature development. But, I suspect the big players could be a little less profitable and deliver a better experience for their end users.

I've used Electron as a developer, too. While it may have been fast & easy at one time, I think that argument is losing merit. Electron had a lot of security holes and patching them has made common tasks harder. Security with Electron is a problem in general given its massive surface area.

Users definitely notice the performance issues. It's certainly not just devs complaining about abstract issues. Yes, people use these tools, but that's mostly out of necessity, not preference. Moreover, big players like VS Code have had to write swathes of the app in C++ for performance reasons.

I look forward to a return to optimizing for the user, not developer velocity. There will likely always be attempts at cross-platform toolkits and there may be a good solution in that space. I hope Electron isn't the best we can do.


> Security with Electron is a problem in general given its massive surface area.

I'm new to Electron development. I've read the docs recommending hardened runtime. Would it be sufficient for security? Can you give examples of such security issues?


Here I was referring specifically to pulling in a web browser as a dependency. Chrome pumps out security releases regularly for all sorts of issues. If you're essentially making Chromium the core of your application, you inherit those security issues (setting aside the fact it may happen in code paths you don't use). And, consequently, you need to keep up on updating Electron and distributing new builds to your end users, even if you haven't made any code changes.

I'm not suggesting every Electron app is a giant bag of vulnerabilities, just that you have a lot more to keep on than you would writing with GTK or UIKit. And, since everything is bundled with the application, you can't rely on OS updates to fix things for you. You need to cut a new release and distribute it.

If you follow the Electron recommendations on security you'll be on the right path. You'll just find common tasks have become harder than they were back when Electron was attracting people with its ease-of-use. I found trying to do type-safe IPC to be an exercise in frustration. If you read the old docs, tutorials, or books, you'll find IPC used to be considerably more free-wheeling. Locking it down is the right trade-off, I think. But there's been an accumulation of many small changes like that. As a result, I don't think the framework is nearly as easy to work with as when Slack or VS Code adopted it.


Thank you for your response. I have previously dealt with IPC for a different project and it was painful indeed.

But I found out that there is this new Preload module in electron that lets you use Node.js very easily via normal export and import. I'm using a popular starter template and it works great so far.


Haven't used VScode, but Slack absolutely sucks IMO (on Linux). I don't even want to install Discord, I use it from the website (but I'm pretty sure the Electron app would be similar to the Slack one).

> Yes it's bulky and sometimes slow, but it offers a lot of features and allow developers to ship features and updates really fast, while only needing one codebase for all platform.

So you are saying that it is bad for the user (bulky and slow), but good for the developer productivity. I really don't see how the users could like the fact that the developers are being more productive while making a worse app.


Using Discord for voice comms in CSGO on Ryzen 3600x w/ 32GB RAM had noticeable impact on my framerate, big enough that I refused to use for this purpose. No impact using Teamspeak. Both in Windows.


electronjs is probably the best cross platform desktops GUI,just a bit heavy.I actually use wxwidgets for GUI desktop apps.


The best cross platform desktop GUI is Qt.


whose license model is a mess unless your GUI is totally open source.


Isn't it just LGPL? Why is that a "mess"?


I'm not a lawyer, I wish it's as simple as "it's just LGPL", it's not.

Otherwise Qt has already conquered the desktop GUI world, it did not for a reason: the license mess.


It did conquer (-ish) the desktop GUI world, for a while: quite a lot of software was written in it.

And then Electron happened.


> And then Electron happened.

Which is worse for users, but better for developer productivity (probably nicer for developers too: C++ is not exactly fun).

I am still hoping that JVM Desktop apps come back at some point, maybe with Kotlin Multiplatform?


You can easily pack every single class file and resource into one single .jar if you desire to do so, no external dependency apart from JRE itself. Oh and of course no installation necessary, just put it anywhere with read access, all works.

At least in the past you could also make a single .exe out of it via 3rd party if you wanted, but I didnt use that for 20+ years so maybe its not valid anymore.


You just add the -static argument, if you want a fully static executable that can run on any linux distro: ‘g++ -o main main.cpp -static’

You can even go above and beyond with cosmopolitan libc v2, which makes c/c++ build-once run-anywhere: https://github.com/jart/cosmopolitan/releases/tag/2.0

There seems to be some work getting cosmopolitan libc support in Go, but it is not ready like it is for c/c++: https://github.com/golang/go/issues/51900

Edit: There can be some problems with using static, if you are using your system package manager for library dependencies. I would recommend compiling dependencies from source using CMake and FetchContent, this has solved pretty much all problems I have had with c++ dependency management.


If you want to distribute app to non tech people you do it via browser ;)


there are many apps that are not suited for a browser :(, on some embedded devices with a touch screen, it does not even have a browser and no internet connection either.


From my POV that is bad example, for those embedded apps you have technical personnel installing and configuring those. Non-technical users don't have any means to install/modify whatever is there.


> Go's major selling point to me is that you can ship one binary, nothing beats that.

Are .war files no longer a thing? ;)


Shipping one binary to install on a users machine has been solved by jlink and jpackage for ages.


How do you distribute a Go library? How do you distribute a Go library that has dependencies?


I'm not sure if your question is rhetorical, but Go doesn't have the concept of compiled library that you can link to another binary.

So in Go you make available the library's source code, and the end-user will download it at build time, or vendor it in the source tree.


Which is a non starter for businesses that don't ship source code.


Businesses that want to sell libraries without a source code license can ship APIs.


Not sure I understand what you mean here. How do I ship the API of my library without shipping the library?


Sure, if they don't care about performance.



Not only it doesn't work in all platforms, it uses a bare bones C API with unsafe code, and it hasn't been removed yet due to backwards compatibility, as Russ Cox already expressed his opinion that plugin was a mistake from his point of view.


> Plugins are currently supported only on Linux, FreeBSD, and macOS, making them unsuitable for applications intended to be portable.

uh-huh

but, in all seriousness: I wonder why that is? I struggle to think of a technical reason that go would be unable to load and invoke a .dll even if one had to name it .so https://github.com/golang/go/blob/go1.21.1/src/plugin/plugin...


Right, so it feels like Go hasn't solved this problem. It just completely ignores it.


I suggest reading about GraalVM...


> Go is simple. It's easy to understand, read, and maintain.

Matter of taste I guess, to me Go code looks ugly, it's too verbose with all that error handling every other line which hurts readability. Also the docs are often so cryptic and unhelpful, one needs to rely on examples elsewhere. I do use it though, when I need something fast in a single binary.


My main pet peeve with Golang is to use single letter or very short abbreviations when naming variables. The Golang documentation recommends what is considered a bad practice by most programmers communities.


Yes, short abbreviations are brutal in long sprawling code contexts. Write in a compact, functional, and readily unit testable coding style, and those tiny variables reduce your cognitive load and bring great clarity. Use comments and/or docstrings to provide context for compact parameters and local variables once, rather than implicitly documenting with every usage.


>Use comments and/or docstrings to provide context for compact parameters and local variables once, rather than implicitly documenting with every usage.

Context that isn't documented with every usage is context you need to remember. Trade off, but I'd much rather not have to remember multiple contexts for the same name every few hundred lines.


Are you specifically referring to method function receiver type annotations? Those are often left shorthand but shouldn't exist out of the type definition file anyway eh?


I’m referring to this guideline:

> Variable names in Go should be short rather than long. This is especially true for local variables with limited scope. Prefer c to lineCount. Prefer i to sliceIndex.

https://github.com/golang/go/wiki/CodeReviewComments#variabl...


One of those is not like the other...

lineCount is literally perfect meanwhile sliceIndex could be anything.


Exception handling and generics are missing key pieces from go. But adding them will make go look like java.

I just wish java would add null safety in the type system in a first citizen way.

For enterprise use java has no competitors. You have c# which is microsoft trying to estabilish nash equilibrium fu*ing the developers. I am a bit worried about ever increasing complexity and a steep learning curve, but seems like this is a problem on all fronts.


Java is an inferior language to C#. To get a superior language you would likely have to go for Kotlin. There is no comparison, because Java gets features today that C# had for years. Not even mentioning having to retrofit green threads because adopting async/await (used by TS, Rust, Swift and other languages) is impossible at this point.


C# does not have virtual threads. What C# has is async/await. Which was nice for its time, but at the same time it's an error prone design, as computations should never start async by accident, blocking should be the default. C# also has no useful interruption model. Java's interruption model is error prone, but at least you can work with it.

Async/await also splits the standard library and the ecosystem in 2 (blocking vs non-blocking, or blue vs red), and it can't automatically update the behavior of old code.

The introduction of virtual threads in Java also works well with "structured concurrency", as seen with Kotlin's Coroutines. Kotlin's approach to concurrency is also superior to that of C#, actually. But what's interesting about Java is that its evolution is often one that involves runtime changes, lifting all boats. Java engineers preferred pushing more changes in the runtime, and somewhat ironically, the JVM ended up being the true multi-language runtime.

Java is a good case study of how languages should evolve. It has extreme backwards compatibility, and features being pushed are assessed for how they impact the whole ecosystem, including libraries or languages not in Oracle's control. Project Loom was developed in the open, compared to what Microsoft usually does.


Do give async/await in C# a try, it has all the structured concurrency features other languages have to invent APIs and special syntax for :)

(if you want to take a look at good structured concurrency, you might be interested in Swift implementation)


I worked with C# professionally.

The async/await syntax works with the language's other statements, but for a long time it had gotchas. It doesn't qualify as "structured concurrency", and it has the aforementioned issues — it's (accidentally) error-prone, it splits the ecosystem in two, and has no interruption model.

I am not familiar with Swift, but I think you can hardly beat Kotlin's implementation. This is a good introduction from Kotlin's lead:

https://www.youtube.com/watch?v=Mj5P47F6nJg


What do you mean by "it splits the ecosystem in two"? I never observed such split, certain methods intentionally offer sync and async variants.

Interruption is achieved through cancellation tokens and has to be handled by consuming methods. There is no way around it because interrupting execution at an arbitrary point would lead to all kinds of issues regardless of the language (unless it implements some form of transaction abstraction and rollbacks all uncommitted changes).


Those "cancellation tokens" from C# are a band-aid.

In Java, you don't need to initialize those "tokens" manually, because the interruption signal is baked into Threads. Moreover, a lot of the standard library cooperates with Java's interruption, which is why you see plenty of methods throwing `InterruptedException`; and it's also reflected in types such as `CancellableFuture` or the `Flow.Subscription` (reactive streams). Of course, user-level code that isn't well-behaved, can end up catching InterruptedException, or resetting the interruption signal, without actually interrupting. This makes Java's interruption model somewhat error-prone, but it's workable, and at least it's baked in.

Note that interruptions could also be preemptive, as you don't necessarily need cooperation. If you think of the call-stack, or flatMap/SelectMany in reactive APIs, the compiled code could check the interruption flag automatically and interrupt the call chain.

And resource leaks aren't necessarily a problem, if the interruption protocol is well-thought-out. In Java, try/finally still works in the presence of interruption, since at worst you get an `InterruptedException`. It's not ideal because you can interrupt the interruption process, and in truth the ideal would be for interruption to be its own communication channel, complementing that of exceptions. But it's totally doable, and here I am familiar with several libraries from Scala's ecosystem, namely Cats-Effect, Monix, and ZIO that show it (with limitations imposed by the runtime).

Either way, what C# provides is basically next to nothing. In fairness, some C# libraries tried fixing it, such as Rx.NET, but it's not enough. And the aggregate result in the .NET ecosystem is that interruption is not something people design for. Like what to interrupt a network socket? This ends up being a setting, presented as a timeout in case of inactivity, as a configuration of the connection, instead of a higher-level generic function that can be applied on the consumer side. And the probability for resource leaks goes up actually, because in the presence of concurrent races, you really need interruption.



Except when there is only one version and someone has to write the transition code.


> regardless of the language

That’s a choice, but it is unfortunate for the programmer. The truly right way to do it all is like Erlang does - where all processes are cancellable and nothing bad happens.


There shouldn't be a reason for a managed language to introduce function coloring. It's horrible.


But async/await is special syntax. I agree it's a nice improvement over using Task APIs directly.


And don't forget to bookmark David Fowler guidelines to avoid all the gotchas that everyone falls into while using async/await.



Java, prints 1:

    Set<File> s = new HashSet<File>();

    s.add( new File( "c:/temp" ) );
    s.add( new File( "c:/temp" ) );

    System.out.println( s.size() );
C#, prints 2:

    ISet<FileInfo> s = new HashSet<FileInfo>();

    s.Add( new FileInfo( "c:/temp" ) );
    s.Add( new FileInfo( "c:/temp" ) );

    Console.WriteLine( s.Count );
C#, test fails:

    string path = "/tmp/filename.txt";
    FileInfo f = new FileInfo( path );

    File.CreateText( path ).Dispose();
    Assert.True( f.Exists );

    f.Delete();
    Assert.False( f.Exists );
https://en.wikipedia.org/wiki/Principle_of_least_astonishmen...

Languages have their strengths and weaknesses.


FilInfo doesn’t override Equal operator in C#. HashSet will use it for comparison and those are two different object references so idk what the confusion is here.


A set is a collection of objects in which order has no significance, and multiplicity is generally also ignored. Observing the code alone, it isn't obvious that two FileInfo instances having the same path are themselves not equal. As has been mentioned elsewhere, FileInfo should not be hashable to prevent declaring it as a Set, avoiding the situation entirely.

C# isn't flawless. Java isn't flawless.


You can’t decide language superiority by the number of features. While C# indeed has many cool features, I do think it has already went into C++ territory where all the different, independently cool features have very non-trivial interactions that make it very hard to reason about.

Also, async-await is not a good thing — virtual threads are superior in every way in case of a managed language.


Why async/await is not a good thing? What makes green threads better? Do you know the difference, the issues async/await addresses that green threads simply do not?


This is code with async/await:

  async fn read_file(filename):
    f = await os.open(filename)
    let data = f.read()
    await f.close()
    return data
this is equivalent code with green threads:

  fn read_file(filename):
    f = os.open(filename)
    let data = f.read()
    f.close()
    return data
As you can see, async/await is pure syntactic noise, it doesn't convey any important meaning.


Async enables clear contract for a type that represents a delayed result.

Better implementations offer eager execution and allow to easily interleave multiple concurrent futures/tasks, like C#. Green threads on the other hand are a workaround to deal with blocking for the most trivial case of cooperative multi-tasking, offering little beyond that.


> Async enables clear contract for a type that represents a delayed result.

It's not really a type, otherwise it would be something like Future<T> in Java and plenty other languages. It is usually implemented as a transformation to a state machine.

Also, Loom is M:N and calling them green threads doesn't give you the whole picture at all. Not exactly sure what you mean by easily interleave -- functionality wise the two is more or less equivalent. You just get to keep your simpler mental model (and tooling) with virtual threads.


with green threads, every result is "delayed" and available exactly when you want it (i.e. as indicated by naive reading of the control flow in code)

> eager execution, interleave multiple concurrent tasks

green threads give you that for free

> deal with blocking

blocking is an implementation detail; both async/await and green threads can be implemented on top of either traditional blocking IO, or callback/non-blocking IO

I'd be even happier to discuss concrete code blocks / examples, that's where the superiority of green threads truly shines


Because they were created to manually run multiple threads on one physical thread, which is the kind of decoupling that a VM/OS is supposed to do for you.



Read David Fowler's guidelines.


Do you have link to any specific article of his (on virtual threads vs async)?



C# is turning into C++, sadly.

It appears every six months there must be new language features being added.

The last one, for declaring fixed size arrays in structs, with an annotation instead of proper grammar change is getting ridiculous.


F# is far superior to C# as a language. If you are going to jump to the .NET runtime that's the tool to go for.


apples and oranges


C# is a better language, but the JVM is a significantly better ecosystem. Java will always be behind (and type erasure for generics is annoying enough as someone who started in C# that I don't think it will ever catch up) but between hotspot and being the preferred language of 2/3rds of the clouds I think it clearly wins.


Type erasure is why there's such a rich ecosystem of 3rd party languages that run on the jvm.


Meaning that it would be harder for those languages on the clr because of generics? Would typing all generics as Object not be essentially equivalent?


   type erasure for generics is annoying
I too have spent significant time programming in both C# and Java. This complaint about type erasure in Java: When does it affect your daily life? There are so many craft workarounds available now that it hardly comes up anymore.

Also, would your opinion of Java significantly change if type erasure was removed or never existed?


I have much more experience in C# then Java FWIW, so you're welcome to take my opinions with a grain of salt. I've had a couple of really annoying errors with Beam serializers that took me way longer to debug then I thought was worthwhile.

I think it is a worse choice, it's too ingrained in the language and ecosystem to change. That and a couple of other nits would likely make me pick Java over C# or Go if I was starting a new project going forward.


If you like jvm, use closure instead.


Sorry you’re down voted. Closure might not be what the author is looking for.

There are a lot of languages you can use with the JVM, Closure is one of them, Groovy, Scala and Kotlin are some more. Kotlin is gaining a lot of traction, especially since it’s backed by JetBrains.


Clojure*


Java 21 doesn't retrofit green threads though. Quasar [0] is a library that implemented fibers for Java and the main developer pron has joined the OpenJDK development team. All that was necessary for first party support is to make the JDK libraries yield when blocking.

Adopting async isn't impossible at all, there is very little demand for it.

[0] https://docs.paralleluniverse.co/quasar/


Async/await is an inferior product compared to threads, for so many reasons (function coloring and meaningful stack traces come to my mind). Keeping the same interface as native thread, plus structured concurrency, are best of breed.

Many uncancellable threads + mutability + goroutine panic kill it all are serious issues for golang.


> I just wish java would add null safety in the type system in a first citizen way

With valhalla (value types), it might just come!


Afaik, no language as great of exceptional handling as Java. I prefer Go but I have to admit, Java's checked exception handling is amazing.


That is an extremely debatable topic. Which is why kotlin completely ignores checked exceptions.

Frankly, Id rather have a result and optional/nullable type like in rust/kotlin than deal with exceptions in any capacity.


Kotlin’s decision to make every exception runtime is the main reason I don’t use Kotlin. It’s especially baffling that they realized the issue with implicit nullability and got rid of it (though not with Java methods, which opens another can of worms), then went and intoduced implicit “exceptionality”.

The correct way to deal with Java’s checked exceptions would have been introducing a Result type, or, preferably, type algebra, like in TypeScript, so something like:

  fun openFile(fileName: String): File | FileNotFoundException {…}
Then you could handle it similarly to null:

  val content: String | FileNotFoundException = openFile(“myfile.txt”).?read()
  …then you have to do a check before you use content as a String…
or

  val content: String = openFile(“myfile.txt”)?.read() ?: “File not found”
(There could also be other possible ways of handling the exception, like return on exception, jump to a handling block, and so on.)

In fact, null should be treated as an exceptional value the same way all exceptions should be.


This would be my preference. I like `Either`or some other container type, but a simple union that makes exceptions explicit works also.


Checked exceptions are gross, they get in the way when you're prototyping, and you end up just ignoring them anyway (since you're prototyping)


The ergonomics of checked exceptions may be debatable but compared to golangs explicit error handling at essentially each function call is definitely worse.


Yeah, I've got a lot of Java experience and a wee bit of Go language experience and I agree with you. I like Go in almost every way except for it's error handling. It's just wrong to have to check every goddam function one by one


I guess that's the reason why most Java programs I use cannot do proper user-facing error messages. Because it is so easy to just ignore error handling. The exception will be caught by the top-level, right? This is how almost every Java cli tool prints a stacktrace on even most trivial user errors like file not found.

Having to deal with errors and forcing the developer to do proper error handling is a good thing.


I don't mind Go's errors. I do mind the complete lack of hierarchy in that. Java's exceptions are hierarchical. I can create an exception that specializes from `IOException` and that I feel is really powerful. Go added this half-baked and much later. So, most FOSS libraries don't support it yet.


Both Java checked and unchecked exceptions are inferior to signaling errors by return values like Go/Rust/Haskell do.

Exceptions are not composable, cannot be generic, and it is not visible in the source code which lines can throw, so every line is a potential branching point.


I don't think the jury will ever return on this topic.


Go has had generics for more than a year now


I agree, Go has had generics for a little while (of course they are different from Java's generics because Go's type system is different from Java's type system) and I don't think the parent comment writer was aware of that.


Not even in the same league as Java.


What is “enterprise” use? Plenty of enterprises use Go.


By enterprise I mean a lot of features related to data consistency, scalability and integrations.

I do not know about go ecosystem, but java and spring have mature solutions that cover the most advanced use cases.


Kubernetes is what I would call very advanced use case.

But that's the thing with Java, yes there are libraries for everything and one could see that as a problem actually.

Spring was mentioned before, but it's the perfect example of an overengineered/ heavy library that does a lot of black magic.


Java is strange because it can be both verbose and magical at the same time.

Just the other day I ran across an issue where spring was wiring things up correctly on Linux but not Windows.


I too dislike dependency injection frameworks. I try to always wire manually myself. I'm tired of debugging old SpringFramework apps where changing the JVM by a patch level or changing one JAR dependency breaks the wiring. I have seen it too many times to count.


Originally prototyped in Java, rewritten in Go when a couple of advocates joined the team.


If all you have is spring boot, everything looks like a spring boot problem.


Plus Spring is honestly quite badly programmed.

The pagination object is bulky and unnecessarily complex, where a simple offset/limit is enough (and a nextUrl for cursor-based access).

When we looked into cluster locks, they’re not even released if one node goes down. I mean, who would need a lock implementation that just stores a line in a DB? And the doc doesn’t even warn about it.

Apache contributors were much better-skilled.


    Apache contributors were much better-skilled.
That is quite a broad statement. Two negative points about Apache Java libraries I can think of: The original "lang" libraries have not aged well at all. Also: The HTTP client libs are a fiasco. Very challenging APIs and weak documentation.


Not really. Software first enterprises do. But most enterprises that have a non-software focus generally prefer languages that have been around for a while and are known by lots of people.


I’ve written go code for large corporates in Australia who absolutely did not have a tech or software focus. One was a notoriously bureaucratic company which used to be a government owned enterprise. For the niches it fills well, it’s become almost ubiquitous.

With regard to this:

> But most enterprises that have a non-software focus generally prefer languages that have been around for a while and are known by lots of people.

I know developers who work for large blue chip financial sector and other traditional sectors. They’re on the same React/Vue/Webpack/whatever treadmill as all the frontend devs devs working at web dev agencies. And they’re often compiling it down from TypeScript, which has not been around for a very long while at all and is not known by lots of people (relative to the size of the JS community.

Swinging a bit of Go for a service in an environment like that isn’t really that hard.


By enterprise he means non-webshit industry.


Wow


The programmers don't make that call. The CTO does, so they can hire anyone.


This is definitely one of those. “Tell me you don’t know .NET with out telling me you don’t know .NET” moments.


> Exception handling and generics are missing key pieces from go. But adding them will make go look like java.

You know that Go has generics since a couple of years now?


Coming from Spring Boot with it's 17+ level deep abstractions to Go / gin-gonic was such a breath of fresh air!


With the little difference that spring boot offers you 99% of your needs, both to fetch the data from (sql, nosql, you-name-it), and to offer your interface out (web, rest), and programming style (syncronous, asyncronous), and observability, ....

while for go you'll find yourself deep in the mud of choosing what 3rd part library to use for logging and how to make it work with the rest of custom stuff you have to write


it's kinda funny to me when people with latest macbooks, loaded with actually useful but comically expensive programs, open up goland that itself has a shit ton of features, to write some error handling in go


I went the other way as I was sick of all the repetition in Go. Spring boot/JPA data repositories save so much SQL, and spring boot automatically marshals to and from JSON, form data, etc. It means you can just work on the meaningful business logic. Add on Lombok and there's even less to maintain.


Go is Java 1.0, nowadays 1.5, as they thankfully finally at least added some support for generics.

I am not touching Go, other than on the projects I have some customer or higher up telling me to do so.


Go gives you the illusion of simplicity because it gets rid of guard rails and error checking. If you remove all error checking, of course your code is going to look a lot simpler. It's also going to be a lot more wrong and crashy.

Wait until your code base grows, your team grows to >10 developers, and you will understand what I mean.

Java (and preferably Kotlin) are a lot more serious about making sure your code is robust before it compiles.


Wait, are you implying Go doesn't have error checking? In what way? It has famously verbose error semantics.


It's verbose yes, but also more error prone.


No exhaustive enum checks.

No Option type, so you can still use results of a function if it returns an error.



I've heard this argument before, and I point out Kubernetes to them. Is that code base complex enough, because it's pure Go doing just fine and runs on plenty of systems?


You can point to a complex project in any language, and that would prove nothing.


I mean, that’s pretty much go’s first complex application that was specifically written with that, so don’t think it is a good example.


> Java (and preferably Kotlin) are a lot more serious about making sure your code is robust before it compiles.

You are making great points for Rust, Ocaml and Haskell.


There isn't all that many plus in their type systems that is not expressible in Java. OCaml and Haskell has Monads, sure. There is Scala for that on the JVM.


> There isn't all that many plus in their type systems that is not expressible in Java.

Thanks to Turing, anything that is Turing-complete can duplicate any other thing that is Turing-complete. So, yes, you can do all of Haskell's types in Java. That is not a flex.

The flex is doing them in a non-horrific way.


The kind of Turing completeness certain type systems have is useless beside academic curiosity - look at the vavr library, that’s what I’m talking about. You can have plenty Haskell types without any hacks, except for Monads in Java.


> vavr - turns java™ upside down

"turn X upside down" are different words for "use X contrary to its original intention and design".

You will find very few people willing to let go what people undestand as Java so as to be able to do Haskell-in-Java.


It’s goddamn immutable collections and Optionals, not brain surgery come on.

It’s not like Java hasn’t been going in the same direction, see records, sum types, pattern matching.


Yes, it's goddamn immutable collections and Optionals.

People still hate it because it's immutable, therefore you can't do hashmap.add(), and it's hard because they can't randomly return nulls, and it's slow because the hashmap now takes o(log n) always instead of o(1) sometimes and o(n) other times.

People hate it because it's different to the Java they learnt 20 years ago, that they claim is exactly the same as today.


Is it possible to express Rust enums (tagged unions) and especially the option type in Java? Ofcourse. But the power of good type system doesn't come from the fact if you can express something, but rather how seamlessly it is integrated in to the language.


Rust has sum types named wrongly as enums, which java also has as sealed interfaces. The option type is just one example for a sum type, which is as easy to express in Java as

  sealed interface Option<T> permits Some<T>, None<T> {
    record Some<T>(T value) {}
    record None<T>() {}
  }
Sure, you have written 3 words more than Rust, and?


Go has made many decisions that i'm not happy about.

If they did one thing exactly right on the language level, it's the [lack of] OOP: interfaces in their implementations, and no inheritance, overridden methods, covariance / contravariance games, etc.

You can of course write in Java in that style: only extend interfaces, never inherit classes. But many libraries, including the standard library, actively refuse to cooperate.


And yet even after writing Go for 5+ years I still have to Google for what actually implements Reader so I can read a file, etc.


Do you mean overloaded methods? You can "override" methods in Go in the sense that if you have an embedded struct you can provide your own implementation in your struct to use instead


Go also sucks. It's so easy to leak threads.


I never understood some of the objections to inheritance. It always made it easier for me to reason about the code, not harder.


Some people are aware about various concepts/paradigms and are able to put each to good use where appropriate.

Other follow fashion and if some dick looking for fame declares A as obsolete and B as the new and shiny one (to be replaced soon anyways) then the lemmings would follow and sing the gospel.


This is correct. It is about culture too. Java is the kind of language that attracts some mediocre programmers who produce mediocre code based on the wrong ideas of object oriented programming. of course, there are great Java programmers. It is just that a better programming language would help average programmers like us to achieve more


That escalated quickly. There are good and less good people everywhere and using language X does not automatically tell anything about you.

If anything I think the cases where you can use Go successfully are only o fraction of the cases where you can use Java successfully. It's not necessarily Java itself but the ubiquity of the JVM and its ecosystem (see Kotlin, see Scala as examplea that have leveraged this ecosystem successfully)


So the ideal blub language will be whatever language is too new to really be the legacy thing with tons of black magic you just have to know, but also too old to include tons of new ideas in language design the programmer has to grapple with.

Old languages force you to understand really core issues because the stack is 1m+ lines of code and you need an operating model for all that magic.

New languages do the same thing, but it's because half the really good stuff is <experimental>

Python and JS are in the current sweetspot, go is up next, and after that, Rust.


> the cases where you can use Go successfully are only o fraction of the cases where you can use Java successfully

could you elaborate why do you think so, and maybe give examples of cases where Go can't compete with Java?..


Libraries for application programming, last time I used Go nothing came close to the Java PDF creation libs for example.


Imho Go is really good for self contained micro-services. The way Go does binaries and the cross-compilation part are great.

Otoh, Java has a huge ecosystem. Huge. This plus dependency managemnt make it the first choice in most cases. Not even going to go into the massive innertia given that Java has been around for decades (who is going to rewrite everything in go?)

Today most of the time I pick Kotlin which is sort of whatbJava could have been (or maybe will become) with proper investment and care.


Let's not forget who golang was made for:

"The key point here is our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt. - Rob Pike


You're entitled to your opinion. I guess I must be a mediocre programmer then. (Don't forget that 90% of developers thinks of themselves as above average.) But if Java can evolve, why wouldn't its practitioners?


In the past, when java was dominant and most popular language - sure.

Today though, with languages like js being the most popular one, I would be surprised if inflow of mediocre developers into Java world would be even the same, not to mention higher, then with those more popular languages (Go included)


This generalisation is easy to explain. On the server-side, Java "won" the enterprise battle. In the last 20 years, big corporates re-wrote their server-side C/C++ stack in pure Java (and thick desktop clients in C#). It is so much easier to maintain than C/C++. As a result, they can hire mediocre Java developers to maintain their "new" legacy services.

    who produce mediocre code based on the wrong ideas of object oriented programming
This overlooks this history of OOP. Each decade, lots of new ideas have emerged so that skilled programmers continue to use the same languages (Java, C#, C++, C), but change how they use them. C++ in 1996? Let's fight about diamond inheritance! C++ in 2006? C++ in 2016? C++ in 2026? Repeat for all four languages that I mentioned. The story will look similar. Anyone good writing new code in these four languages isn't using many levels of inheritance. It is gone. Sure, it exists in the language for historical reasons, but it is hardly used in new code. "Prefer composition over inheritance."


And some people for no fucking reason think that they're smarter than everyone else and are qualified to tell others how they should go about they business.


> attracts some mediocre programmers who produce mediocre code

That will be reality for most companies, no matter the language. And if Java projects still got delivered in such conditions - it might also be a mediocre language but it is also just good enough.


Yeah that's not going to be too popular but Java in particular has a tech culture problem. It's way more common to find overengineering and overabstractions in Java projects than any other language.

The language itself might be fine but I'll never touch it because of that.


Despite the fact that this is a claim with no basis in reality, what you are saying is that people who don't understand the core concepts the language is built on write bad code...Isn't that true for every language?


This is also the killer argument for going Python, by the way. Go is going to be much faster, of course, but you can still scale quite well with just going Python. And sometimes / most often you don't need scale.


I use Go and Java every day, and Java is way more enjoyable to use


Lol...you use the language most appropriate for the given situation. What's appropriate in the browser....hmmm. Can't slam your foot down on that one.


> The packaging is like how you would package files on your computer in single folders

How does that vary from Java?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: