Channel Directions in Rust

In Rust, we can specify whether a channel is for sending or receiving values when using them as function parameters. This specificity increases the type-safety of the program.

use std::sync::mpsc;

// This `ping` function only accepts a channel for sending
// values. It would be a compile-time error to try to
// receive on this channel.
fn ping(pings: &mpsc::Sender<String>, msg: String) {
    pings.send(msg).unwrap();
}

// The `pong` function accepts one channel for receives
// (`pings`) and a second for sends (`pongs`).
fn pong(pings: &mpsc::Receiver<String>, pongs: &mpsc::Sender<String>) {
    let msg = pings.recv().unwrap();
    pongs.send(msg).unwrap();
}

fn main() {
    let (pings_tx, pings_rx) = mpsc::channel();
    let (pongs_tx, pongs_rx) = mpsc::channel();

    ping(&pings_tx, String::from("passed message"));
    pong(&pings_rx, &pongs_tx);
    println!("{}", pongs_rx.recv().unwrap());
}

To run the program:

$ cargo run
passed message

In this Rust version, we use the std::sync::mpsc module to create channels. The Sender and Receiver types are used to specify the direction of the channel.

The ping function takes a &Sender<String>, which can only send values. The pong function takes a &Receiver<String> for receiving and a &Sender<String> for sending.

In the main function, we create two channels using mpsc::channel(). We then pass the appropriate senders and receivers to our functions.

This approach ensures type safety at compile-time, preventing misuse of the channels.