Ask HN: Is Go simplicity worth it?
For high level programming, is the value of simplicity really that important, realistically? I'm talking about manifestos like the [grug brained developer](https://grugbrain.dev/) and [harmful.cat-v.org](http://harmful.cat-v.org/software/java) where most rants point at Go as a better alternative. From my personal experience, Go is very nice to develop in exactly because of the focus on simplicity, but I'm struggling to find a realistic use for Go. Want to build a web-stack? Modern tools like Next.js, web workers, supabase etc. makes this process very easy, even though you have to write JS/TS which does not value simplicity as highly. New tech like Blazor and LiveWire lets you ditch the API pattern altogether when all you want to ship is a website. These techniques can reduce complexity in terms of how much code you need to write and maintain by ditching the frontend-backend bridge, but might introduce more complexity overall by having to use, say, C# for Blazor which is ever-growing with complexity and over-engineering. So, is it worth still sticking to Go and go with the good old fashion backend API + frontend pattern in your opinion?
When it comes to low level programming and simplicity, I struggle to find use cases for Go since we are often looking for real-time and highest performance (which Go compiler prefers speed over optimization). However, I think I'm starting to prefer C over Rust after writing a little C and previously a lot more Rust. Because I simply don't see the benefit of kinda-but-not-really-guaranteed safety with a lot of added complexity and cognitive load over the simplicity of Go or C for general purpose development. I.e. development where safety isn't a priority, because then I think Ada would be a better fit with stronger safety guarantees, no?
And sorry if it's controversial. I'm not looking to start a flame war, but I'm genuinely interested in learning different opinions on the matter.
20 comments
[ 358 ms ] story [ 1589 ms ] threadThe larger issue with Go, which Go enthusiasts will downvote me for, is that it allows for writing absolutely garbage code that is impossible to read. Readibility is king in software development, and developers spend 80% time reading it. I won't go into the details here, but Go has no constraints for how code should be structured, leading to spaghetti code. I have first hand experience, and 30 years professional experience.
Regarding your experience with readability in Go, I have to agree in some way because the known (and controversial) explicit error handling, but what you may realize sooner or later is that handling both the happy path and erroneous path is actually a net positive. That's the difference between seeing `if err != nil {` as code pollution or actual logic. I've realized the latter.
https://news.ycombinator.com/item?id=38128698
And then the language itself forces class based programming (which isn't really OOP), which I heavily dislike due to it only over-complicating things in the long run. C# provides largely the same, but MS is actually way more open than Oracle as in it's easy to get documentation and the dev environment set up, and they provide newer and more modern features than Java. Which is surprising given it's Microsoft and their fetish for providing counter-intuitive and user-unfriendly products. When it comes to the JVM / .NET CLR, the only place I find it acceptable is on the server side IMO. The downgrade in performance (which means higher resource usage) side is not worth the "everything is an object" vision for me, at all. Not even close. Client side devices often run on battery power, so that has real consequences there.
So that's why I'm personally not the biggest Java fan. In fact, if anything on harmful.cat-v.org is true, it's "Java is write once, run away" for me... sorry. If only Oracle could provide the same user-friendliness that Microsoft is showing with .NET, ditch class-based programming (which means rewrite the entire language, not very realistic) then maybe it could be interesting, but most likely not better than Go or Node.js, in my experience anyways.
And by the way, what do you mean by threads that really work? It's cool that Java gives you the power of having system threads and green threads in the same environment, but when is that realistically needed? Only time I can think of is writing client-sided code where you want performance to be highly optimized and not wanting to waste time on organizing a new green-thread, but as I've mentioned I believe Java on the client side is nothing but a sin.
There's lots of other places where a developer might want something that's quite fast, but doesn't drag along a lot of dependencies. Any microservice system debugging or performance analysis might fall in that category. Incident response for kubernetes or even data center racks of servers might, too.
A lot of microservices that are horizontally scaled would fit that, too. You don't want huge containers with detailed configurations, because that's hard to get correct, slow to load and probably has a lot of attack surface. A minimal container would make it harder for an attacker to use access to gain further access. Sprawling Java apps are the opposite of that.
Not because they aren’t excellent, but because they aren’t great to work with. C# and .Net has never been greater than they are now, and yet we increased our productivity by switching to Node/Typescript by around 20%, with the added benefit of having a single language across the stack. The latter was the primary reason for the switch and the increase in productivity came as a sort of surprise and we’re honestly still trying to figure out why our developers produce things which are measurably better at a faster pace with TS and for many a change of tech from something they’ve used for many years. I see some similar reflections and stories coming from the lunar team on why they switched from Java to Go.
That being said. Whatever works is always the best technology. If that’s C, C#, PHP or whatever, then that’s always going to be your best answer. I don’t think there is really any reason to “pick” the right technology from the get go, you can always worry about that when/if it becomes a problem. We didn’t switch to TS from C# because we disliked it, we did it to share our resources better. Eventually if/when we grow enough, we’re likely going to have to change things. Though maybe not. Lego seems to be doing fine on mainly Node and I doubt will reach their size any time soon.
After looking around at the current popular solutions, I've yet to find something that is as ergonomic and productive as the .NET stack in regards to creating a web-based product. You have one of the most solid backend frameworks (ASP.NET) with lots of great tools like EF Core for ORM, SignalR for real-time, now Blazor for frontend, easy authentication and authorization, etc. That just makes everything so performant.
However, that is a very high level focused development path, while I feel Go is slightly lower level where you still have pointers and such. I see it as great for CLI apps and very specific server needs where you'd want great performance and CSP threading in combination with a very easy syntax for new developers, but I don't think that's a very common use case to be honest. Even though I love Go for its focus on simplicity, it just isn't the most suitable lang for high-level work, nor is it very suitable for low-level work at the same time.
Regarding your switch from C# to TS, I understand it made sense in the last couple of years. It simplified the stack via reducing language context switching, which can be a good productivity boost depending on your team and team size. However, if you would've tested Blazor today and found it would have satisfied your frontend needs, I actually think a full C# stack will be better than TypeScript to be honest, due to the better tooling and better runtime that exists for C# compared to Node.js/Bun/Deno. I still think TS is better in the frontend department than Blazor, but that's simply because JS/TS has been the only language for frontend in a long time. I hope Blazor will gain traction as a real alternative.
The productivity gains come somewhat in spite of using a single language and sharing resources. On one had this will play out nicely over time, but on the other hand we had to transition a lot of developers and tax others to help the process along. I can’t tell you exactly why we’re seeing it. The general consensus is that it’s just “nicer to work with Typescript” but I suspect it’s also because our internal developer tools are just better for Typescript. Not so much because we couldn’t have made them for C# but because we, had, to make them for Typescript.
As far as performance goes, all our heavy computation happens in C++ and for everything else the performance difference between the .Net vm and Node is negligible at our scale.
You may think it’s odd, but we’re hardly the only organisation doing it. Lego did it a few years back to great success.
There have been very few instances of vulnerabilities with nuget. If you compare the numbers to npm, they might as well be a rounding error.
Perhaps your experience was shaped by poorly written ancient codebase specific to your company (or, as I strongly assume, also influenced by select few niche libraries you personally dislike), but it just does not translate to the experience of other developers (of whom you can read numerous testimonies here on HN). I pity the devs who had to suffer moving away from C# to TS and possibly C++, where especially the latter has migraine-inducing build system, and overall is a significant user experience downgrade.
You’re also correct in assuming that I don’t dislike .Net or C# as techs, it’s their batteries I dislike. I’ve mentioned a few in my previous posts, mainly EF, OData and AD. But I’ve never worked with a “batteries” included tech in C# I didn’t eventually have to extend. Even something as simple as making a rest client has been a fight against the standard tools, and I’m not exactly alone in this. There is a reason libraries like RestSharp exist. Hell even something more simple like the GUID generic doesn’t actually produce valid UUIDs, which means other languages won’t be able to verify them. Not an issue if you stay within the ecosystem, but if your front-end is JavaScript, you’ll need to either write your own, find a 3rd party or extend the base type. All of these things, can, be negligible. Many of them like the basic http client has improved. But over time, if your business processes require it, I’ve just never had to fight a language as hard as I have with C#.
I wouldn’t personally recommend moving from C# to TS for shits n giggles. We did it to pool dev resources, but it’s been a joy to work with. Which is interesting considering it’s also made by Microsoft. I do think C# is adopting more and more of the JavaScript ecosystem, and more and more of how Types are simply superior to classes, which is very neat, so I do think C# is heading in an ever better direction. But its standard libraries aren’t. And if you can’t use those, then why would you really chose C# over something like Go or Java?
Even within the .Net ecosystem itself, I think that Powershell has now far surpassed the usefulness of C# for basically anything related to Operations. In many cases I think Powershell is even superior to Python. Except of course for the fact that you can use Python for other things, so you again can get more out of those dev resources, but Powershell has a purpose where C# does not. Not really.