3 ms·
As someone who likes async/await/coroutines, I really miss them in Go. Channels are the GOTO of synchronisation, they lead to confusing spaghetti code because t
by hinoki 4y ago
As someone who likes async/await/coroutines, I really miss them in Go. Channels are the GOTO of synchronisation, they lead to confusing spaghetti code because there is no structure.
Go is really nice to read (once you get used to the fact that half the lines of code in any function are for error handling) unless it uses a lot of channels. Then you need to take great care to understand every <-.
- dom96 4y ago> As someone who likes async/await/coroutines, I really miss them in Go Interesting. Most complain about languages with async/await and say they want goroutines. What is it about async/await that you prefer over Go's approach?
- zinodaur 4y agoNot OP, but I am also in the camp of "like goroutines, not a fan of channels". Low cost threads are great - but channels can represent so many intermediate states, especially when error handling is involved. I wish there was a simpler default for coordinating goroutines (Do we add an error field to the struct we send through a channel? Do we close the channel on error, or only on success? Do we make a separate channel to send errors on - and if we close that one it means for sure that there were no errors? If we select on the two dependent channels, do we have to make sure that they are in different sequential selects, so that we don't go out-of-order or deadlock?)
- hinoki 4y agoAsync/await allows you to be much more explicit about dependencies. I don’t care what thread executes something, but I do care that e.g. these three network requests happen in parallel. With async/await I can explicitly use an ‘await Promise.all(a, b, c)’ where Go would need a new channel and goroutines, etc. all being implicit, so it’s hard for the reader to know what the intent is, and it’s error prone, who knows if you properly clean everything up.
- morelisp 4y agoThis is a weird example as Promise.all and Promise.race are what are pretty easy to write in Go: Promise.all is trivial: return <-a, <-b, <-c Promise.race is a little longer: select { case x := <-a: return x case x := <-b: return x case x := <-c: return x } What Go doesn't do very well compared to promises is composing; composing channels, especially with error returns, is usually tricky. But async/await are also bad at this. Passing around the actual promise/futures objects is the best way, which is for some reason discouraged today in favor of await/async noise in most cases.