Select in Rust

Rust’s select! macro allows you to wait on multiple channel operations. Combining threads and channels with select! is a powerful feature of Rust.

use std::thread;
use std::time::Duration;
use std::sync::mpsc;

fn main() {
    // For our example we'll select across two channels.
    let (tx1, rx1) = mpsc::channel();
    let (tx2, rx2) = mpsc::channel();

    // Each channel will receive a value after some amount
    // of time, to simulate e.g. blocking RPC operations
    // executing in concurrent threads.
    thread::spawn(move || {
        thread::sleep(Duration::from_secs(1));
        tx1.send("one").unwrap();
    });

    thread::spawn(move || {
        thread::sleep(Duration::from_secs(2));
        tx2.send("two").unwrap();
    });

    // We'll use `select!` to await both of these values
    // simultaneously, printing each one as it arrives.
    for _ in 0..2 {
        select! {
            msg1 = rx1.recv() => println!("received {}", msg1.unwrap()),
            msg2 = rx2.recv() => println!("received {}", msg2.unwrap()),
        }
    }
}

To run this program, you would typically save it as select_example.rs and use cargo run if it’s part of a Cargo project, or rustc select_example.rs followed by ./select_example if compiling directly.

The output would be:

received one
received two

Note that the total execution time is only ~2 seconds since both the 1 and 2 second sleep operations execute concurrently.

In Rust, we use thread::spawn to create new threads, which is similar to goroutines in concept. The mpsc::channel() function creates a multiple producer, single consumer channel, which we use for communication between threads. The select! macro in Rust provides similar functionality to Go’s select statement, allowing us to wait on multiple channel operations simultaneously.