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

As someone who hasn't written C# regularly for over a decade, but has done Go every now and then recently, why would you replace C# with Go? It sounds like it would be a step down in maintainability with not much advantage.


Long term c# dev, who's used golang on a few projects. I really want to love go with an htmx+templ, amazing speed and gc, but find it sort of weird/quirky and just plain tedious in use.

Linq in c# is so nice, and lots of little c# features(maybe too many) in recent years has made it quite nice for daily use. With aot definitely prefer c# the language over golang. I do sort of loathe aspnet/mvc and especially blazor stuff. We desperately need a better web framework than asp but nothing will ever gain enough traction because of the ms dominance. Microsoft the sprawling corp never fails to disappoint, but damn the .net framework team does do some awesome work.

That said, I'm instead putting future efforts into python because let's be honest, uv/fastapi/fasthtml are more than fast enough for nearly every single project I've ever worked on.


We work with solar data, which involves a myriad of data formats and delivery systems. This is mainly because solar inverter engineers didn’t think anyone would put solar inverters directly on the internet. It even said so with big red block letters in one of their manuals. Anyway, basically the entire industry decided to never read the manuals and just put the inverters directly on the internet.

Which means we’ve collected data with various services. Especially because it used to be done by different parts of the business, which means some of it is in power apps, some of it is in Python some of it is in C#, some is in Typescript and some is in C. We want to lessen that and GO fits our purpose better than C# because of how async/await has been inherently flawed from its creation. A big part of this is developer based, because of how it was designed it’s just very easy to fuck it up. It’s very leaky and you need to propagate everything, it’s very easy to create deadlocks and you can’t cancel tasks in any meaningful way. On the technical side it’s just terrible for our use case, we’ve cut our Azure cost immensely with go-routines compared to C#. The biggest cost saving has obviously been with power apps, followed by Python but because of the amount of data we handle C# is also very expensive. On the philosophical side of things. We prefer things like explicit error handling and not having to create a class to have a function.

So a lot of it isn’t technical, and some of it is.


Tasks specifically allow to never worry about the kind of race conditions you get with WaitGroups and channels for unary cases - after all, you `await` the result immediately, or later on, and even if you do it multiple times with a Task<T>, it is foolproof and will not allow you to make a synchronization mistake because there is no synchronization to do by the user.

They are also cheaper than Goroutines if that's what you want to say: https://gist-github-com.translate.goog/neon-sunset/8fcc31d68...

In addition, all meaningfully cancellable operations accept 'CancellationToken' which is way easier than goroutine context passing, some overloads also accept timeout instead if that's expected to be the main use of that.

You could make a case about preference for different language syntax and expressiveness, different quality of an SDK from a particular vendor, but the technical arguments made here just do not correspond to reality.


You're not really making a lot of argumentation to back up your claims. Anyone can Search engine benchmarking and get the results they want. Just look here:

https://karl-pickett.medium.com/benchmarking-a-toy-c-task-vs...

Hell, you can even test things yourself:

https://go.dev/src/runtime/stack.go

For our specific use case C#'s TPL was ok, but it comes with a massive overhead compared to Goroutines. We can have tens of thousands concurrent threads running at the same time at very little CPU usage (which is primarily what we pay for). It’s not that you can’t use async/await tasks to do the same, but they use a lot more CPU and as such is less cost effective for us.

As far as blocking and having meaningful (again meaningful is the keyword) cancellation I encourage you to look to Microsoft and understand the limitations outlined by them in the learning articles starting here:

https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous...


>Anyone can Search engine benchmarking and get the results they want.

>you can even test things yourself

The link he provided above, as well as below and in other comments, are his own benchmarks, not something he searched for.


> You're not really making a lot of argumentation to back up your claims. Anyone can Search engine benchmarking and get the results they want.

This is only possible if you completely ignored the text in my comment and never used C# and Go concurrency primitives side-by-side to evaluate them on their merits. The race conditions risks in Go are very real and so are issues w.r.t closing channels, passing nils, etc. The __much higher___ cost of spawning channels and gorotines is equally as real and you can measure it yourself. Both are intended to be spawned for longer than shortlived scenarios. But even then, you will run out of memory much faster if you have thousands of goroutines waiting on a timer channel versus tasks waiting on PeriodicTimer. This does not make either choice strictly better than the other as both have their tradeoffs but tradeoffs nonetheless that must be acknowledged (like pros and cons of implicit suspend, stackless vs stackful, etc.).

You can also take the data from the code snippets from the gist I linked and replicate it with current versions of Go and .NET on your own machine. This is the perfect case that illustrates how much memory consumption you will see with massive amounts of mostly-suspended-periodically-calling-a-service Tasks and Goroutines. But you did not and have a history of constructing arguments in bad faith, not actually discussing strengths and weaknesses of a particular language.

Not sure what is the purpose of the link for tasks (which does not talk about cancellation, this one does: [1]) and Go's stack implementation. I'm very well aware of both, which is the driving reason to respond here to salvage the discussion with otherwise wrong claims.

Lastly, the data from 2019 is irrelevant because it uses completely different threadpool implementation and is likely measuring also the one-time cost of JIT compilation for code. .NET has significantly evolved since then and provides much better native compilation[2][3] than Go today, as well as much higher throughput[3][4] code w.r.t GC and JIT for long-running services.

[1]: https://learn.microsoft.com/en-us/dotnet/standard/parallel-p...

[2]: https://news.ycombinator.com/item?id=41234851

[3]: https://benchmarksgame-team.pages.debian.net/benchmarksgame/... (not listed there but if you compile any of the submissions, .NET tends to produce binaries twice as small as Go ones)

[4]: https://gist.github.com/neon-sunset/72e6aa57c6a4c5eb0e2711e1...

[5]: https://gist.github.com/neon-sunset/c6c35230e75c89a8f6592cac...


You realize you can change the default memory stack on go routines right? I mean, I’m just going to ignore anything you say going forward as this stalking of you is beyond silly, but at least get things right.


World does not revolve around you, it's an infantile outlook :)

I simply see a discussion that might be interesting and respond to comments related to topics I feel proficient at.

In any case, how many deployments realistically adjust their goroutine stack size? What are the implications of starting with <500B-1KiB default stack (because asynchronously yielding task will use as little as <100B)?


> You are about to hear a long tirade how OData is terrible (has little to do with .NET) or some arbitrary reason from this particular HN account.


You are about to hear a long tirade how OData is terrible (has little to do with .NET) or some arbitrary reason from this particular HN account.

In practice, it’s often management decision and has little value as .NET usually has better tooling like gRPC one.


You should get a healthier hobby than stalking me.




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

Search: