Okay so probably the closest thing to understand is something like a waitgroup. With a waitgroup, you declare it as a variable, call Add passing in the number of concurrent processes you want to wait for to complete. Put a call to the Done() method of the waitgroup at the end of each concurrent method. And then at the line you want to wait for the concurrent functions to wait to complete you call the Wait() method of the waitgroup. Channels are a bit like queues, you can write data onto them and read from them and they’re thread safe. There are ways to use them to wait for a concurrent process to complete but I don’t personally use them for that very often. I’m sure others will elaborate Answer from DarkOverNerd on reddit.com
🌐
Reddit
reddit.com › r/golang › can anyone tell me how async/await works comparing to goroutine model?
r/golang on Reddit: Can anyone tell me how async/await works comparing to Goroutine Model?
October 27, 2024 -

I am a student and have some experience in languages that use an async/await approach for concurrency, and not really practiced that as extensively as Go's model.

What i have gathered from online resources is that an "async" function, can be called with the "await" keyword, to actually wait for the async function to complete. But isn't this basically a single threaded program as you have to wait for the async function to complete?
What is the async/await equivalent to Channels? How do you communicate between two concurrent functions?

Can anyone explain this to me, or guide me to some resources that can help me to understand this?

🌐
Hacker News
news.ycombinator.com › item
Goroutines and Async-Await are two very different takes on the same problem. In ... | Hacker News
May 7, 2019 - In C# or Python 3, each function is colored as either sync or async. You can quite easily call an async function from a sync context, but doing a blocking sync call from an async context is forbidden (although possible) · In Go there is no such distinction: you just write your functions in ...
Discussions

node.js - async-await vs goroutines + channel, which is better performence for handling many WebSocket connection? - Stack Overflow
most people think that goroutine is better than async/await. because goroutines combine parallel and concurrent. but what I know is that node js itself is not really a single thread. because every ... More on stackoverflow.com
🌐 stackoverflow.com
python 3.x - Goroutines vs asyncio tasks + thread pool for CPU-bound calls - Stack Overflow
OTOH, memory sharing across goroutines is akin to memory sharing across threads rather than asyncio tasks since goroutine execution order guarantees are much weaker (even if the hardware has only a single core). More on stackoverflow.com
🌐 stackoverflow.com
C# Task async/await vs Golang's goroutines
C# Task is similar to goroutine in the sense that it is also an abstraction on top of physical threads. It's not. Task and Thread are in general unrelated. You can have one without the other (e.g. you can have Task representing a group or succession of other tasks, Task representing an I/O operation, etc.). However, it is considered a bad idea to do blocking I/O (e.g., do .Result) inside an async Task because "the entire thread will be blocked, causing deadlock". It doesn't necessarily cause a deadlock. It can in some cases cause one when using certain kind of synchronization contexts (e.g. in UI) but this sentence in general is not correct. Calling a blocking function (or property such as .Result) will "block" the thread ; but that is not the same as a deadlock. C# (.NET) threads are "managed" threads so they don't always map to a given (or single) native thread. More in the BoTR . More on reddit.com
🌐 r/csharp
18
27
June 3, 2023
go - C# Task async/await vs Golang's goroutines - Stack Overflow
I have been learning both C# and Golang for a while and trying to compare the ways they support asynchronous programming. What I know about goroutines is that the go runtime can schedule the gorout... More on stackoverflow.com
🌐 stackoverflow.com
🌐
Rust Programming Language
users.rust-lang.org › help
Golang Goroutines/Channels vs Rust Async/Await - help - The Rust Programming Language Forum
January 10, 2022 - Hello everyone. I am a (mostly) Golang programmer trying to dabble into Rust. I am very much familiar with Go Goroutines/Channels concept for multithreading and such. However, Rust does not seem to follow this pattern. Instead, it follows the Async/Await model of JS.
🌐
Quora
quora.com › Is-async-await-in-Node-js-similar-to-Goroutines
Is async/await in Node.js similar to Goroutines? - Quora
Answer (1 of 5): Node.js has the very most rudimentary form of concurrency, through non-blocking I/O. Basically, you bind a callback and go do another thing, when the I/O finishes, it triggers the callback. async/await and Promises are nothing but an abstraction on top of that. Go is an entirel...
🌐
Medium
alexyakunin.medium.com › go-vs-c-part-1-goroutines-vs-async-await-ac909c651c11
Go vs C#, part 1: Goroutines vs Async-Await | by Alex Yakunin | Medium
July 20, 2020 - All the magic associated with them happens when you start them with “go” syntax: Go starts them concurrently in a lightweight thread — in fact, a thread that uses a very small stack (that can grow though) and is capable of asynchronously awaiting on channel read operation by suspending itself and releasing the OS thread to another lightweight thread. There is no “await” concept in Go: instead, goroutines are supposed to use channels to communicate.
Top answer
1 of 2
12

I think I know part of the answer. I tried to summarize my understanding of the differences, in order of importance, between asyncio tasks and goroutines:

1) Unlike under asyncio, one rarely needs to worry that their goroutine will block for too long. OTOH, memory sharing across goroutines is akin to memory sharing across threads rather than asyncio tasks since goroutine execution order guarantees are much weaker (even if the hardware has only a single core).

asyncio will only switch context on explicit await, yield and certain event loop methods, while Go runtime may switch on far more subtle triggers (such as certain function calls). So asyncio is perfectly cooperative, while goroutines are only mostly cooperative (and the roadmap suggests they will become even less cooperative over time).

A really tight loop (such as with numeric computation) could still block Go runtime (well, the thread it's running on). If it happens, it's going to have less of an impact than in python - unless it occurs in mutliple threads.

2) Goroutines are have off-the-shelf support for parallel computation, which would require a more sophisticated approach under asyncio.

Go runtime can run threads in parallel (if multiple cores are available), and so it's somewhat similar to running multiple asyncio event loops in a thread pool under a GIL-less python runtime, with a language-aware load balancer in front.

3) Go runtime will automatically handle blocking syscalls in a separate thread; this needs to be done explicitly under asyncio (e.g., using run_in_executor).

That said, in terms of memory cost, goroutines are very much like asyncio tasks rather than threads.

2 of 2
1

I suppose you could think of it working that way underneath, sure. It's not really accurate, but, close enough.

But there is a big difference: in Go you can write straight line code, and all the I/O blocking is handled for you automatically. You can call Read, then Write, then Read, in simple straight line code. With Python asyncio, as I understand it, you need to queue up a function to handle the reads, rather than just calling Read.

Find elsewhere
🌐
Reddit
reddit.com › r/csharp › c# task async/await vs golang's goroutines
r/csharp on Reddit: C# Task async/await vs Golang's goroutines
June 3, 2023 -

I have been learning both C# and Golang for a while and trying to compare the ways they support asynchronous programming.

What I know about goroutines is that the go runtime can schedule the goroutines to run on different physical/machine threads. If a goroutine is blocked (e.g., synchronous waiting for I/O), the go runtime can suspend the goroutine and free the physical threads to run other goroutines.

C# Task is similar to goroutine in the sense that it is also an abstraction on top of physical threads. However, it is considered a bad idea to do blocking I/O (e.g., do .Result) inside an async Task because "the entire thread will be blocked which might cause deadlocks (e.g., GUI app)". Can't the C# runtime do something similar to goroutines to suspend the blocked async Task and free the physical threads to run other async Tasks?

I have been struggling for this problem for a while and couldn't find public materials explaining this better. Maybe my understanding is not correct. Can someone please help me?

Top answer
1 of 5
31
C# Task is similar to goroutine in the sense that it is also an abstraction on top of physical threads. It's not. Task and Thread are in general unrelated. You can have one without the other (e.g. you can have Task representing a group or succession of other tasks, Task representing an I/O operation, etc.). However, it is considered a bad idea to do blocking I/O (e.g., do .Result) inside an async Task because "the entire thread will be blocked, causing deadlock". It doesn't necessarily cause a deadlock. It can in some cases cause one when using certain kind of synchronization contexts (e.g. in UI) but this sentence in general is not correct. Calling a blocking function (or property such as .Result) will "block" the thread ; but that is not the same as a deadlock. C# (.NET) threads are "managed" threads so they don't always map to a given (or single) native thread. More in the BoTR .
2 of 5
11
Here's the short, simplified version. With go, you can write synchronous code and the runtime will ensure it doesn't actually block the underlying thread. The go keyword is involved here somewhere, I'm not a go expert. With .Net, the runtime doesn't do this so if you write synchronous code it will block the thread. To avoid blocking the thread you use the await keyword and call the async version of the method, e.g. CallApiAsync() instead of CallApi(). Your application will be compiled as an async state machine. The complexity to suspend and resume tasks is inside your application, rather than in the .Net runtime. From a developer perspective it's all roughly the same. Neither implementation is inherently more performant than the other. The difference is one language requires more async/await/task syntax than the other.
Top answer
1 of 1
28

Making value judgements is always a tricky thing so I'll highlight 3 differences. You decide whether they fall into the "pro" or "con" bucket.

  1. While both Go and async allow you to write async code in a straightforward way, in .NET you have to be aware which part of your code is async and which one isn't (i.e. you have to explicitly use async/await keywords). In Go you don't need to know that - the runtime makes it "just work", there is no special syntax to mark async code.

  2. Go design doesn't require any special code in standard library. .NET required adding new code to the standard library for every async operation, essentially doubling API surface for those cases e.g. there's new async http download API and the old, non-async http download API has to remain for backwards compatibility.

  3. Go design and implementation is orders of magnitude simpler. A small piece of runtime code (scheduler) takes care of suspending goroutines that block on system calls and yielding to sleeping goroutines. There is no need for any special async support in standard library.

.NET implementation first required adding the aforementioned new APIs. Furthermore .NET implementation is based on compiler rewriting code with async/await into an equivalent state machines. It's very clever but also rather complicated. The practical result was that the first async CTP had known bugs while Go's implementation was working pretty much from the beginning.

Ultimately, it doesn't really matter. async/await is the best way to write async code in .NET. Goroutines are the best way to get that in Go. Both are great, especially compared to alternatives in most other languages.

🌐
Medium
medium.com › @kartik11buttan › go-routines-concurrency-in-go-vs-async-await-in-javascript-are-they-same-d9417cee462b
Go Routines: “Concurrency” in Go vs “Async/Await” in JavaScript. Are they same? | by Kartik Buttan | Medium
July 16, 2024 - Go routines and channels make up ... gives clean syntax for asynchronous operations, Go routines turn out to be much better at scaling and ease of use for concurrent programming....
🌐
Boot.dev
blog.boot.dev › rust › concurrency-in-rust-can-it-stack-up-against-gos-goroutines
Concurrency in Rust; Can It Stack Up Against Go's Goroutines? | Boot.dev
May 11, 2020 - Goroutines are very different from async/await. Async/Await explicitly accomplishes concurrency, but not necessarily parallelism. In other words, while async/await logically executes two functions at once, it doesn’t always practically do so.
🌐
HackerNoon
hackernoon.com › asyncawait-in-golang-an-introductory-guide-ol1e34sg
Async/Await in Golang: An Introductory Guide | HackerNoon
November 28, 2020 - It has powerful features like Goroutines and Channels that can handle asynchronous tasks very well. Also, goroutines are not OS threads, and that's why you can spin up as many goroutines as you want without much overhead, it's stack size starts at 2KB only. So why async/await?
🌐
DEV Community
dev.to › syawqy › concurrency-showdown-goroutines-and-channels-vs-cs-asyncawait-and-tpl-32pb
Concurrency Showdown: Goroutines and Channels vs. C#'s async/await and TPL - DEV Community
March 29, 2025 - Go's approach makes the concurrency pattern more explicit, with channels clearly showing the flow of data between goroutines. Both languages support timeouts, but with different approaches: ... public async Task<string> FetchWithTimeoutAsync(string ...
🌐
DEV Community
dev.to › wagslane › concurrency-in-rust-can-it-stack-up-against-go-s-goroutines-elo
Concurrency In Rust; Can It Stack Up Against Go’s Goroutines? - DEV Community
May 11, 2020 - Goroutines are very different from async/await. Async/Await can accomplish concurrency, but not parallelism.
🌐
Reddit
reddit.com › r › golang › comments › 6p3e0g › go_vs_c_part_1_goroutines_vs_asyncawait
r/golang - Go vs C#, part 1: goroutines vs async-await
July 24, 2017 - What is the point of that? They're not going in parallel, it's a sequence. Why use channels and goroutines here?