使用相同的 Rust 通道 (mpsc) 发送不同类型

Vin*_*nie 5 types channels rust

我遇到了一种情况,我正在为多个发送方设置通道,这些发送方需要能够将不同类型的数据发送到接收线程。

使用以下匹配表达式创建接收线程来处理这些消息。

let receiver_thread = match config.style.as_str() {
    "Type1" => start_recv_type1(receiver, config.clone(), log.clone()),
    "Type2" => start_recv_type2(receiver, config.clone(), log.clone()),
    "Type3" => start_recv_type3(receiver, log.clone()),
    _ => panic!("Wrong type!"),
};
Run Code Online (Sandbox Code Playgroud)

可以发送的一种可能类型是 String 而另一种是我定义的结构。但是,编译器抱怨接收线程上的类型不匹配。查看我的接收者和发送者的定义方式,我可以明白为什么这是不正确的,因为它具有以下类型:std::sync::mpsc::Receiver<std::string::String>.

看看我的匹配表达式,我认为创建一个更通用的函数来初始化我的接收线程是更明智的,但我如何通过同一通道发送不同类型的数据?我已经搜索并找到了一个可能的解决方案,即使用将我的结构和字符串作为字段的枚举,但这是否意味着我必须更改所有函数定义才能使用此枚举语法?即更改我的功能以使用ChannelTypes(StringMessage(String))ChannelTypes(StructMessage(factory::datatype::MyStruct))

enum ChannelTypes {
    StructMessage(factory::datatype::MyStruct),
    StringMessage(String),
}
Run Code Online (Sandbox Code Playgroud)

Luk*_*odt 8

一个特定的通道只能发送一种类型的数据。正如您所注意到的,发送者的类型为 type Sender<String>,接收者的类型为Receiver<String>。所以两者都固定在String. 没有办法解决这个问题(有充分的理由!)

首选的解决方案实际上是使用 enum,是的。事实上,您尝试模拟枚举会为您做什么:您有一个标签来描述期望的数据类型。在您的尝试中,您使用字符串作为标签。但出于多种原因,这是一个坏主意。当您使用枚举时,将使用整数标签(更好),并且 Rust 会为您处理它们。更强大的解决方案。

一个建议:您可能会发现将枚举类型视为消息更有用。事情就是这样:您向另一个线程发送消息。该消息可能是多种不同类型中的一种。接收线程必须检查到达的消息类型,然后才能处理它。

  • 是的,如果大小存在很大差异,那么您可以“装箱”消息内容。 (3认同)

d9n*_*gle 5

这是一个枚举示例:

use std::sync::mpsc::{self, Receiver, Sender};

enum Fruit {
    Apple(u8),
    Orange(String)
}

fn main() {
    let (tx, rx): (Sender<Fruit>, Receiver<Fruit>) = mpsc::channel();

    tx.send(Fruit::Orange("sweet".to_string())).unwrap();
    tx.send(Fruit::Apple(2)).unwrap();

    for _ in 0..2 {
        match rx.recv().unwrap() {
            Fruit::Apple(count) => println!("received {} apples", count),
            Fruit::Orange(flavor) => println!("received {} oranges", flavor),
        }
    }
}

// output:
// received sweet oranges
// received 2 apples

Run Code Online (Sandbox Code Playgroud)