5 ms·
I obviously can't see your code, but in my experience, working with Go daily for years, explicit channels are an extremely rare occurrence. If you want to run
by cube2222 5y ago
I obviously can't see your code, but in my experience, working with Go daily for years, explicit channels are an extremely rare occurrence.
If you want to run multiple tasks and wait for them to finish, you use a WaitGroup. If you want to stop processing on first error encountered, you use an ErrGroup. And cancellation with contexts also works very well overall.
I actually think Go does it way better than all the "visible async/await" languages. Because usually when you write code, you just want to await the result, so in Go, awaiting is the default. In order to run a task without awaiting immediately, you use the 'go' keyword (at least that's the semantics of it all). It also omits the function coloring problem (this is a very big advantage), because all functions are async.
For my use cases channels are usually only useful in two situations:
1. Asychronous producers and consumers.
2. Creating an "actor" which receives messages on a channel/s and processes them in a serialized manner. Where the messages come from multiple event sources.
As an aside, I do understand why performance oriented languages like Rust choose the async/await path, as async by default carries a performance penalty / requires a runtime. I don't however accept it in non-performance oriented languages.
- akiselev 5y ago> As an aside, I do understand why performance oriented languages like Rust choose the async/await path, as async by default carries a performance penalty / requires a runtime. I don't however accept it in non-performance oriented languages. Ironically, I think Rust futures could be expanded into Go-like uncolored functions relatively easily without even much of a runtime. Since they're stack allocated by default, driving a future to completion is a matter of calling Future::poll in a while loop and handling the waker callback. I feel like the runtimes are there mostly to provide a unified interface to kernel APIs like io_uring/epoll/etc and ease ownership/task allocation.
- Animats 5y agoGo really does do this better. Go is a green thread system. In Rust, if you're actually doing any compute work, you're stalling out the async system. In Go, if you compute for a while, the scheduler will let someone else run. You can get all the CPUs working. This is well matched to writing web back ends. Rust's "Async" seems to be designed for a very specific use case - a program running a very large number of network connections, most of which are waiting. If you're doing something where you need all available CPUs to get the work done, it's a bad fit.
- anderskaseorg 5y agoYou make it sound like Rust doesn’t support background CPU computation. Rust has always had threads (https://doc.rust-lang.org/book/ch16-01-threads.html https://doc.rust-lang.org/book/ch16-01-threads.html), along with incredibly powerful libraries like Rayon (https://github.com/rayon-rs/rayon https://github.com/rayon-rs/rayon) to take advantage of them. async/await wasn’t specifically targeted for that use case because it didn’t need to be. But you can use threads with async, if you want, using a multi-threaded scheduler like Tokio with the rt-multi-thread feature flag (https://docs.rs/tokio/1.7.0/tokio/runtime/index.html#multi-thread-scheduler https://docs.rs/tokio/1.7.0/tokio/runtime/index.html#multi-t...).
- staticassertion 5y ago> In Rust, if you're actually doing any compute work, you're stalling out the async system. Just use threads? Or add explicit yields.
- Animats 5y agoexplicit yields. That's so 1984 Macintosh. "Cooperative multitasking". The usual effect of that style of programming is stuck window managers.
- staticassertion 5y agoYou still get preemption at the thread level.
- pcwalton 5y agoSo use threads! That's what they're there for. Go's solution is threads, just with a particularly idiosyncratic M:N implementation. Rust threads are 1:1. But they're the same concept. You can even get M:N if you really want it (nobody does, which is why mioco gets no use).
- jjav 5y agoExactly. It's painful that the same problems get revisited as new things. Computation needs to be scheduled to a CPU or core for parallel progress to occur. That means kernel threads.