| > Calling a function directly forces it to run on the same execution thread as you. Calling it with await allows it to run in any thread. This is the actual advantage, and Go doesn't have any equivalent construct that is as convenient for this use case. OK so Thread A calls “await” on a coroutine that executes in Thread B (where B may or may not be A). Thread A is now blocked on that coroutine. What have I gained by running that coroutine in Thread B? One potential answer is that while Thread A is blocked by “await”, it can context-switch to a different coroutine. You can effectively do similar things in Go if you want to. But doing so abandons the guarantee that Thread A will pick up where it left off as soon as Thread B is finished. > Also, note that a function that expects to return data through channels can't be called in a sync manner in Go or it will deadlock. So in essence there is function coloring in Go as well. Is this a popular or idiomatic interface for Go library code to the same degree it is for “async” libraries in other languages? In isolation I find it more understandable to do channel writes as an explicit side effect than to manage futures but maybe that’s just my brain. > Not out of the box, but they are easy to replicate if desired I’m pretty sure you could implement futures and async/await using Go channels too if you wanted to. |
Futures, maybe (though without generics you'll be either very dynamic or write a new future for each struct, of course).
But async/await is a syntactic feature and can't be implemented in a language without macros and/or continuations. Basically `await` is a keyword which returns a future that will execute the rest of the function as written. Something like this is relatively easy to implement:
You could re-write it to something like this in Go: Or something similar. Maybe you could even reduce the boilerplate, though it's already much worse than the C# verison. But this is much more difficult to re-write in Go: Assuming you want to keep the asynchronicity, this gets much uglier to implement in terms of channels (not that this is very common code).