I've got a situation where I am setting up channel with multiple senders that need to be able to send different types of data to a receiving thread.
A receiving thread is created to handle these messages using the following match expression.
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!"),
};
One possible type that can be send is a String while the other is a struct I've defined. However, the compiler is complaining about mismatched types on the receiving thread. Looking at how my receiver and sender is defined I can see why this is incorrect because it has the following type: std::sync::mpsc::Receiver<std::string::String>
.
Looking at my match expression, I think it's wiser to create a more generic function to initialize my receiving thread but how can I send different types of data over the same channel? I've searched and found a possible solution by using an enum that has my struct and a string as fields but does that mean I will have to change all my function definitions to use use this enum syntax? I.e. change my functions to use ChannelTypes(StringMessage(String))
or ChannelTypes(StructMessage(factory::datatype::MyStruct))
enum ChannelTypes {
StructMessage(factory::datatype::MyStruct),
StringMessage(String),
}
One particular channel can only send one type of data. As you noticed, your sender has the type Sender<String>
and the receiver has the type Receiver<String>
. So both are fixed on String
. There is no way around this (for good reasons!)
The preferred solution is actually to use an enum, yes. In fact, you try to emulate what an enum would do for you: you have a tag that describes what kind of data to expect. In your attempt you use strings as tags. But that's a bad idea for a multitude of reasons. When you use an enum, integer tags (much better) are used and Rust handles them for you. Much more robust solution.
One suggestion: you might find it more useful to think of your enum type as message. As that's what it is: you send a message to another thread. And this message could be one of many different types. The receiving thread has to check which kind of message arrived and can then handle it.
Here's an example with enum:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With