For the features that overlap between golang and .Net, can someone please let me know why people choose .Net over golang for non legacy systems? As far as my limited knowledge goes, go is much more efficient in syntax and memory.
The languages are very different. C# has much more powerful abstractions and is a much larger language in general. That is both an advantage and a disadvantage. Modern C# is also very fast, I wouldn't bet on Go winning that comparison.<p>My experience with Go is a while back, before it got generics. While I liked the overall idea of a language with little syntax and a focus on simplicity, I didn't really like Go in the end. It was a weird mix of too low-level and high level code. It exposed low level details that I don't need to think about in C#, and it is missing convenient abstractions like LINQ.<p>Personally, I like async/await in C# more than Go concurrency. I know this is heretical here, but I don't care about function coloring or any of the abstract advantages of other concurrency approaches. Async/Await in C# works for me (in non-legacy code) and is easy to understand.
the main problem with the .net async/await is the immediate execution of a call returning a Task, without control over where it may execute. F#'s asnyc was way saner and easier to understand in my opinion.<p>I'd beg to differ on the easy to understand... last time i worked with this stuff like ConfigureAwait only has cargo cults and no real good explanation, and wasn't covered in any recent version of eg. CLR via C#... Distributed tracing and thread management were totally bitten by async, also the way iterators and LINQ were broken... that was when I got off the train, as it broke the best abstractions for line of business code so that instead of designing an IO pipeline lazy developers could simple put Task.Run around blocking IO calls at the bottom of the codebas, and ... yeah, we are back at function coloring.<p>This brings me to: I winder for what kind of apps did you find it a delight, because for extensive data wrangling leveraging multiple calls it was a pain.
You don't need ConfigureAwait() at all in modern C# (unless you're writing desktop UI code, I don't know enough about that to comment there). In a modern ASP.NET Core web application you don't care about which thread your Task executes, there is no synchronization context at all.<p>I'm using C# for the backend of a web application, not legacy but .NET Core from the start.
> unless you're writing desktop UI code<p>Indeed, you need a <i>crapload</i> of ConfigureAwait() in desktop UI code, and it infects all underlying libraries that might have to run inside a desktop app. The worst thing they ever added to our beautiful language. It's a dream to work in ASP.NET without needing to pepper every await with a ConfigureAwait().<p>That said, I don't agree with the characterization of ConfigureAwait() as un-understandable. We understand it. We just hate it.
Sometimes you do care where it executes, and then it starts to become a problem ;).<p>Something which was as easy as an IO call in the middle of a function running on a thread pool becomes a PITA if the IO call is cleverly async-ized (by wrapping the original sync IO method into a Task.Run(), but actually this is the better case!) ad then removed from the public API... (cannot recall the exact library, but it was a pain, as it was some core stuff, maybe vendored by MS themselves)<p>Also back then it caused us loosing correlation IDs as those were thread locals in traditional pre-async ASP.Net Core (think version 0.9-2.0 when I worked on that part, then up until core 4 and the async mania continuos broke readable calculation code in LINQ, TPL based performant data pipelines, etc...) and with async execution started to migrate between threads... If you needed high performance you already used threads, because it was not a classic web application, but a specialized optimization algorithm with a web api... and if you need more than CRUD, and use all the cores (and SIMD) to squeeze out all performance you have, you hit these problems right away. These all could be solved, but it actually broke stuff, a lot of stuff, as developers jumped on the fad, and it their sync code was turned into a .ConfigureAwait(false /* Microsoft blogs talk a lot about it without a clear explanation, so every cool kid does this */).GetAwaiter().GetResult()... then you some of your threaded code silently broken if you dare used Thread Locals... Faded memories, but that was when they f'ed up the C# language.
That's why I emphasized <i>modern</i> .NET. All I/O should be using async methods through the entire application. Wrapping sync code in async causes troubles, but that is entirely avoidable in new code. That's the price you have to pay to make this particular abstraction work well, everything I/O must be async.
Modern C# is a much more powerful and expressive language than Go: iterators, collection expressions, records, async await, source generator, much more powerful generics, low level memory management features like Span<T> and ref struct, etc. It is closer to C++ with opt out GC/opt in AoT than it is the old Java comparison days.<p>Go's advantage is mostly the fast compile speed, goroutines, profiling, and a very opinionated formatter. Neither has an overwhelming advantage over the other though.
Go is not much more efficient, compared to NativeAOT - though it can be faster in some areas. The big reason why someone would want to use C# is that it's a more expressive language. You can even write your DB queries with LINQ (C# lets you express code as data), making them type-safe.
Modern .net is surprisingly performant while also being very high level if needed. So it is very close to being a "learn once" ecosystem. This means you use it to write code for a much broader range of usecases than others, you will have a broader / more mature ecosystem than others, and your potential hiring market is more vast.
Go isn't as much fun. And is usually slower for my work until I bump up the GC and then it uses roughly the same amount of memory.<p>I have also found c# async to be lighter than go's concurrency story, and dotnet11 is going to make that much more clear.<p>Now: I write software for fun, not for money.
I know it's not quite as important in the agentic world, but the .NET tooling (across Visual Studio, JetBrains Rider, and C# Dev Kit for VS Code) is just awesome. Some people might frown upon full-blown IDEs, but sometimes they're just incredibly handy.
That is an urban myth, CLR was designed with support for C++ in mind.<p>Also Go is at the stage of C# .NET 2.0, and still plenty of lacking language features.<p>I really think the creator of C# made a disservice to the .NET community by picking Go for the Typescript rewrite.
Go still has a better deployment story. Single static binary deployment are king. On .Net 8 I was hitting random compatibility issues with single binary application bundles, with System.Data.SQLite, and other libraries. (had to use that one and not he Microsoft one for some legacy compatibility reason, maybe around Guid handling maybe)
Is cp -r/xcopy/robocopy a folder (with or without tar/zip wrappers) that much harder than single file deployment?
From your description you certainly weren't using AOT compilation, and forgetting about CGO.<p>Static linking as the only way in most platforms, we moved into other mechanisms for a reason.<p>In Go the only way to do plugins, without shipping everything as source code is to use microservices, the more fashionable name for multiple process with OS IPC.
The tooling and development UX.<p>Put things like their remote debugging experiences side-by-side and you will quickly learn why some of us go for the Microsoft tools rather than the others.
Exactly C# with .NET is batteries included type of ecosystem where most of stuff is done by Microsoft and if someone is experienced with the stack he can whip up enterprise ready app in no time.<p>I don’t have much experience with Go lang but what I have seen, there is lots of things one has to implement on his own. Which has its own merits, but to go from 0 to full fledged enterprise app you need more time.
I'm not a .NET person by any stretch and have been more of a Go person traditionally, but I think from what I've seen IRL, this is accurate.<p>Go is trying to be like C. Less language features (until recently...), so to solve problems you write more code. Intentionally simple language. Intentionally need a lot of code to implement something substantial. .NET seems more frameworks driven. Go traditionally has eschewed frameworks for doing stuff much like C tends to eschew framework type stuff and prefers smallest dependency reliance as possible.
Every new release of Go brings some of the features that have been available for twenty years in .NET (and every other language), like generics. Some features, like ergonomic error handling (whether or not you think unchecked exceptions are a good idea), Go has said will never be available. There isn't much to recommend about Go. It's fast to do the mediocre thing, faster than any language, but for a serious code-base intended to be maintained long-term, C# has better libraries, established patterns and frameworks, abstraction features, developer ergonomics, etc.
Compare the ecosystems of .NET vs golang. No comparison whatsover. IoT, mobile, web (front and backend), cloud, etc. I think Go lacks variety and is more focused on traditional greybeard areas.
Native interop is much better in .NET, that matters a lot for some systems.
There's one (usually minor) caveat here, which is around strings. In .NET, like Windows*, strings are UTF-16. If you call into native code that uses UTF-8 strings extensively, then they have to be marshalled (when passed to native code) and unmarshalled (when received from native code), which takes additional time and memory. I've run into this lately, which has led me to write special CStr/CString types (idea borrowed from Rust) to avoid unnecessary, especially round-trip, (un-)marshalling.<p>* = Technically, Windows now supports the UTF-8 "code page" where applications can use UTF-8 natively, but all NT system calls use UTF-16, so the conversion still has to happen somewhere
C# in .NET 11 adds support for UTF-8 string literals (`ReadOnlySpan<byte> str = "Some sample string."u8;`) which is a step to making such interop easier.<p>The Runtime has explored attempting "UTF-8 native" string storage as a platform feature especially for Linux FFI, but yeah Windows using UTF-16 is still a compatibility issue where platforms themselves just don't agree.
> go is much more efficient in syntax and memory<p>I'm going to talk about the second part first. .NET is often deployed with a JIT compiler runtime like Java. That means that hello-world scripts use a lot more memory than Go, but that difference becomes a lot smaller on real-world programs and .NET can use less memory than Go depending on what you're doing.<p>C#'s concurrency can also be more efficient than Go's since it's coroutine based async/await is a lightweight state machine rather than green threads. That's not to say Go is especially heavy or anything, but it is more overhead.<p>In terms of "efficient in syntax", Go has a lot fewer features. That's one of Go's biggest strengths and weaknesses.<p>Here's an example. With Go, you just have struct tags: strings of anything that can be attached to a field in a struct. Let's say you have a User struct and you want to make it so the JSON won't have the user's email in it. You do: Email string `json:"-"`. But what if you mess up and write "jsom" or `json:-` without the quotes? It's basically a meaningless string to the compiler. With C#/.NET, you have annotatons/attributes that are a part of the language and checked as types. You'd do: [JsonIgnore] public string Email. JsonIgnore is an attribute class so your IDE can help you.<p>There's a lot in Go where the answer kinda becomes "f-it, we'll just use strings instead of having something meaningful." Go talks about how important error handling is, but then you get an error from a function and it's basically just a string. If you're doing good error handling, you want to handle different errors differently, but that's not easy in Go. Frankly, it's not easy in most languages, but this is definitely an area where it felt like Go gave up on creating something good in order to get something out the door quickly enough that Google didn't cancel the project. In a language like Zig, errors are enums and you get exhaustiveness checking. With Go, someone could add another error state to something you're using and you'd never know - or they could change the phrasing of an existing error and you'd silently stop matching on it.<p>Go's lambda syntax is clunky. func(x MyType) string { x.ToString(); } vs (x) => x.ToString()<p>There's lots of stuff like that. I'm not arguing that Go is bad, but it has a ton less stuff and that's both a blessing and a curse.
What's go's equivalent of LINQ?
At former jobs, because people know it and switching from .Net <-> Go generally isn't worth the time to learn other language.<p>Sure, having a runtime is downside but difference in container size for your average CRUD App doesn't really matter. Performance IME is very similar.<p>Ops type here.
Well for me, that's like asking why don't you write everything in Erlang rather than C#.<p>Go is for me just a, hmm, concurrency programming language. Its popularity stems just from being pushed by Google, and the cosmetics of using braces. Despite what pundits say, it's completely and utterly not like C.<p>While C# is a successful and comfortable everything-language. It is blazing fast, has amazing tooling, you can get going to prototyping, then enterprise code, its serverside handling is excellent. It has many low level features and built-in data structures. It's I would say preferable for almost any kind of work except scripting. (I really don't like C# scripting.)
.net has a much stronger ecosystem and more experienced developers.<p>Golang is a fantastic delightful language, but it's still missing a lot of stuff that's existed in C# for years.<p>However, do you *need* all those .net tricks?<p>Golang is usually enough for a small project you need to build in a weekend. Scaling it to a mono repo with 200 developers might be a bit difficult
In addition to what the others have said, I also enjoy the extremely robust ringtone reflection system in .NET. I don't know of any other systems that provide more complete detail. Maybe Java, though it's been a while since I've used it. It makes reflection in other languages feel prehistoricaly primitive.