Is there a Rust library which mimics closely the Go [goroutines / channels / select] paradigm ?
Or in other words, is there a Rust library which would allow one to translate Go code to Rust code nearly literally, i.e. a Rust library with:
Channels,
Buffered channels,
Unbuffered channels (blocking channels),
A select mechanism to switch to the active channel amongst a set of channels (the one which is currently receiving data) without having to check all channels of a set one by one linearly.
A mechanism to close a channel once all data have been send down said channel.
A corresponding mechanism on the receiving end to check if a channel has been closed by a sending routine.
So, the main thing you are requesting are channels. While the standard library features a basic one ::std::sync::mpsc, I think that using dedicated crates will lead to richer APIs as well as enhanced performance. One important thing to observe here is given the precise / explicit nature of Rust, the asyncvs. non-async difference is important. I'd say that the async ecosystem etc. may get you closer to Go's goroutines; but if you don't have too many "tasks", then good old thread spawning and using non-async channels might work as well.
Actually, looking at its API, it seems to feature async primitives as well!
async channel libraries
As mentioned, flume might actually cover this case as well;
a runtime agnostic library.
And now for the potentially runtime "biased" libraries, which also means they're guaranteed to have optimal interaction with said runtimes:
The whole sync module of the tokio framework is quite well documented and definitely battle-tested for production.
This is the crate used by the async-std framework to handle channels
Select-ing
In the async world, I recommend tokio's select! macro to perform this: the idea is that once you have several async tasks (outermost futures), you can, inside an async context, select on their completion. And receiving (and blocking-sending) from (async) channels yield such futures.
Some things to be mindful of in Rust's async world
The following blog post may not be the best entry-level read for async Rust, but it does talk about some pitfalls / footguns in this environment. Special mention to select!-ed futures which may not be polled to completion if they don't win the first "race": for a select!-ed future to be polled to completion, it needs to be enqueued onto an executor beforehand, through the .spawn() method:
Finally, when dealing with Futures and the async world, Pin and Unpin will come back from time to time. In that regard, the following blog post has proven to be quite good at clarifying the situation:
Generally, for a nice blog post with practical examples, both the tokio guide, and the blog of one of its main maintainers, @alice, feature some interesting reads, such as: Actors with Tokio – Alice Ryhl
My approach to getting Go like threads and channels in Rust was to skip all the heavy duty study of how Rust does async, futures, pin, etc, and just go straight to Tokio: