Rust language desde la entrada hasta la serie de competencia: comprensión profunda del canal de Tokio (Parte 1)

rust_tutorial_logo.pngEl lenguaje Rust es un lenguaje de programación a nivel de sistemas que está fuertemente tipado y es seguro para la memoria. El módulo Tokio en el lenguaje Rust es una biblioteca de programación asíncrona que proporciona una manera eficiente de manejar tareas asíncronas. Entre ellos, el canal es una parte importante del módulo Tokio, que se puede utilizar para transferir datos entre tareas asíncronas. En este tutorial, presentaremos el canal del módulo Tokio en Rust y brindaremos algunos ejemplos para ayudarlo a comprender mejor cómo usarlo.

¿Qué es el Canal del Módulo Tokio?

Un canal en el módulo Tokio es un mecanismo para pasar datos entre tareas asincrónicas. Es similar a una tubería en un sistema operativo y puede pasar datos entre diferentes tareas asincrónicas. Los canales del módulo Tokio tienen las siguientes características:

  • Se puede pasar cualquier tipo de datos entre tareas asincrónicas.
  • Admite múltiples productores y consumidores.
  • Se admiten operaciones asíncronas.

El canal en el módulo Tokio se divide en dos tipos: mpsc y oneshot. Entre ellos, mpsc es un canal de múltiples productores y un solo consumidor, y oneshot es un canal de un solo productor y un solo consumidor.

Crear un canal mpsc

En el lenguaje Rust, crear un canal mpsc es muy simple usando el módulo Tokio. Primero, debe agregar la dependencia del módulo Tokio en el archivo Cargo.toml:

[dependencies]
tokio = { version = "1.28.0", features = ["full"] }
复制代码

Luego, importe el módulo Tokio y el canal mpsc en el código:

use tokio::sync::mpsc;
复制代码

A continuación, se puede crear un canal mpsc usando la función mpsc::channel():

let (tx, rx) = mpsc::channel(32);
复制代码

En este ejemplo, creamos un canal mpsc de tamaño 32 y devolvemos dos objetos: tx y rx. tx es un objeto emisor, que se puede usar para enviar datos al canal, y rx es un objeto receptor, que se puede usar para recibir datos del canal.

Enviar y recibir cadenas

Aquí hay un ejemplo simple que muestra cómo enviar y recibir cadenas entre tareas asincrónicas:

use tokio::sync::mpsc;

#[tokio::main]
async fn main() {
    let (mut tx, mut rx) = mpsc::channel(32);

    tokio::spawn(async move {
        tx.send("hello".to_string()).await.unwrap();
        tx.send("world".to_string()).await.unwrap();
    });

    while let Some(msg) = rx.recv().await {
        println!("{}", msg);
    }
}
复制代码

在这个例子中,我们首先创建了一个大小为 32 的 mpsc channel。然后,我们使用 tokio::spawn()函数创建了一个异步任务,该任务向 channel 中发送了两个字符串。最后,我们使用 while 循环从 channel 中接收数据,并打印出来。

发送和接收数字

下面是一个示例,演示如何在异步任务之间发送和接收数字:

use tokio::sync::mpsc;

#[tokio::main]
async fn main() {
    let (mut tx, mut rx) = mpsc::channel(32);

    tokio::spawn(async move {
        tx.send(1).await.unwrap();
        tx.send(2).await.unwrap();
        tx.send(3).await.unwrap();
    });

    while let Some(msg) = rx.recv().await {
        println!("{}", msg);
    }
}
复制代码

在这个例子中,我们创建了一个大小为 32 的 mpsc channel。然后,我们使用 tokio::spawn()函数创建了一个异步任务,该任务向 channel 中发送了三个数字。最后,我们使用 while 循环从 channel 中接收数据,并打印出来。

发送和接收结构体

下面是一个示例,演示如何在异步任务之间发送和接收结构体:

use tokio::sync::mpsc;

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
}

#[tokio::main]
async fn main() {
    let (mut tx, mut rx) = mpsc::channel(32);

    tokio::spawn(async move {
        tx.send(Point { x: 1, y: 2 }).await.unwrap();
        tx.send(Point { x: 3, y: 4 }).await.unwrap();
    });

    while let Some(msg) = rx.recv().await {
        println!("{:?}", msg);
    }
}
复制代码

在这个例子中,我们创建了一个大小为 32 的 mpsc channel。然后,我们使用 tokio::spawn()函数创建了一个异步任务,该任务向 channel 中发送了两个结构体。最后,我们使用 while 循环从 channel 中接收数据,并打印出来。

发送和接收元组

下面是一个示例,演示如何在异步任务之间发送和接收元组:

use tokio::sync::mpsc;

#[tokio::main]
async fn main() {
    let (mut tx, mut rx) = mpsc::channel(32);

    tokio::spawn(async move {
        tx.send((1, 2)).await.unwrap();
        tx.send((3, 4)).await.unwrap();
    });

    while let Some(msg) = rx.recv().await {
        println!("{:?}", msg);
    }
}
复制代码

在这个例子中,我们创建了一个大小为 32 的 mpsc channel。然后,我们使用 tokio::spawn()函数创建了一个异步任务,该任务向 channel 中发送了两个元组。最后,我们使用 while 循环从 channel 中接收数据,并打印出来。

发送和接收枚举

下面是一个示例,演示如何在异步任务之间发送和接收枚举:

use tokio::sync::mpsc;

enum Message {
    Text(String),
    Number(i32),
}

#[tokio::main]
async fn main() {
    let (mut tx, mut rx) = mpsc::channel(32);

    tokio::spawn(async move {
        tx.send(Message::Text("hello".to_string())).await.unwrap();
        tx.send(Message::Number(123)).await.unwrap();
    });

    while let Some(msg) = rx.recv().await {
        match msg {
            Message::Text(s) => println!("{}", s),
            Message::Number(n) => println!("{}", n),
        }
    }
}
复制代码

在这个例子中,我们创建了一个大小为 32 的 mpsc channel。然后,我们使用 tokio::spawn()函数创建了一个异步任务,该任务向 channel 中发送了两个枚举。最后,我们使用 match 语句从 channel 中接收数据,并打印出来。

多个生产者和单个消费者

下面是一个示例,演示如何在异步任务之间使用多个生产者和单个消费者:

use tokio::sync::mpsc;

#[tokio::main]
async fn main() {
    let (tx1, mut rx) = mpsc::channel(32);
    let tx2 = tx1.clone();
    let tx3 = tx1.clone();

    tokio::spawn(async move {
        tx1.send("hello".to_string()).await.unwrap();
    });

    tokio::spawn(async move {
        tx2.send("world".to_string()).await.unwrap();
    });

    tokio::spawn(async move {
        tx3.send("!".to_string()).await.unwrap();
    });

    while let Some(msg) = rx.recv().await {
        println!("{}", msg);
    }
}
复制代码

En este ejemplo, creamos un canal mpsc de tamaño 32 y usamos la función tx1.clone() para crear dos nuevos objetos emisores: tx2 y tx3. Luego, usamos la función tokio::spawn() para crear tres tareas asincrónicas, cada una de las cuales envía una cadena al canal. Finalmente, usamos un bucle while para recibir datos del canal e imprimirlos.

Enviar datos usando BufferedSink

Aquí hay un ejemplo que muestra cómo usar BufferedSink para enviar datos:

use std::io::Write;
use tokio::io::BufWriter;
use tokio::sync::mpsc;

#[tokio::main]
async fn main() {
    let (mut tx, mut rx) = mpsc::channel(32);

    tokio::spawn(async move {
        let mut writer = BufWriter::new(std::io::stdout());
        while let Some(msg) = rx.recv().await {
            writer.write_all(msg.as_bytes()).unwrap();
            writer.flush().unwrap();
        }
    });

    tx.send("hello\n".to_string()).await.unwrap();
    tx.send("world\n".to_string()).await.unwrap();
}
复制代码

En este ejemplo, creamos un canal mpsc de tamaño 32. Luego, usamos la función tokio::spawn() para crear una tarea asíncrona que escribe datos en la salida estándar usando un BufferedSink. Finalmente, usamos la función tx.send() para enviar dos cadenas al canal.

Use la macro select! para seleccionar el mensaje que llega primero

Aquí hay un ejemplo que muestra cómo usar la macro select! para seleccionar el mensaje que llega primero:

use tokio::sync::mpsc;

#[tokio::main]
async fn main() {
    let (mut tx1, mut rx1) = mpsc::channel(32);
    let (mut tx2, mut rx2) = mpsc::channel(32);

    tokio::spawn(async move {
        tx1.send("hello".to_string()).await.unwrap();
    });

    tokio::spawn(async move {
        tx2.send("world".to_string()).await.unwrap();
    });

    loop {
        tokio::select! {
            Some(msg) = rx1.recv() => println!("{}", msg),
            Some(msg) = rx2.recv() => println!("{}", msg),
            else => break,
        }
    }
}
复制代码

En este ejemplo, creamos dos canales mpsc de tamaño 32. Luego, usamos la función tokio::spawn() para crear dos tareas asincrónicas, cada una de las cuales envía una cadena al canal. Finalmente, usamos la macro tokio::select! para seleccionar el mensaje que llega primero e imprimirlo.

en conclusión

En este tutorial, presentamos el canal del módulo Tokio en el lenguaje Rust y brindamos 8 ejemplos para ayudarlo a comprender mejor cómo usarlo. Ya sea que sea un desarrollador de Rust novato o experimentado, hay algo útil que aprender de estos ejemplos. Si desea obtener más información sobre otras funciones del módulo Tokio, consulte la documentación oficial del módulo Tokio.

Supongo que te gusta

Origin juejin.im/post/7229487528175747131
Recomendado
Clasificación