【问题标题】:Sending different types using same Rust channel (mpsc)使用相同的 Rust 通道 (mpsc) 发送不同的类型
【发布时间】:2020-02-25 04:21:03
【问题描述】:

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

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

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!"),
};

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

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

enum ChannelTypes {
    StructMessage(factory::datatype::MyStruct),
    StringMessage(String),
}

【问题讨论】:

    标签: types rust channels


    【解决方案1】:

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

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

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

    【讨论】:

    • Enum 可能是一个问题,如果它的变体在内存大小上有相当大的差距。 Rust 也会为最小的变体分配最大的尺寸。
    • 是的,如果大小有很大差异,您可以Box邮件内容。
    • 感谢您的回复,如果我理解正确,我应该只创建一个名为 MessageTypes 的枚举,并有 2 个称为 MessageA 和 MessageB 的变体。 Rust 将每个变体分配给一个整数值,因此每个变体具有相同的大小。但是,我怎样才能在函数中使用我的 2 个变体?我需要获取这些枚举中的 String 或 Vec 值。我是否必须在这个枚举上编写一些带有 impl 的方法,以便能够与底层数据进行交互?有一个例子会很棒..
    • @Vinnie 您只需使用match 来匹配枚举。然后您可以访问随附的数据。不是偷懒,而是the book has a nice chapter on that。我希望这会有所帮助!
    • 谢谢,成功了,我想太多了。为了将来的参考,我将我的类型 (String, Vec) 包装成 2 个枚举变体。我在接收站点上使用 match 来解开枚举,在发送端我正在创建我在 MessageType 中包装的批量数据,如下所示:pub fn create_batch(timeseries: Vec<String>) -> Option<MessageType>
    【解决方案2】:

    这是一个枚举示例:

    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
    
    

    【讨论】:

      猜你喜欢
      • 2021-12-18
      • 2021-11-09
      • 1970-01-01
      • 2021-07-29
      • 1970-01-01
      • 2021-05-30
      • 2023-03-18
      • 2020-08-29
      • 1970-01-01
      相关资源
      最近更新 更多