我有 Golang 背景,正在开发一个 Rust 项目,该项目具有以下设置:
我有一个基于 2 个通道的标准生产者/消费者设置:“工作通道”和“结果通道”。
生产者线程将工作发送到工作通道并从结果通道接收结果。
消费者线程从工作通道接收工作并将结果发送到结果通道。
我在 Rust Playground 中创建了一个最小可重现的问题示例(粘贴在下面)。 [注意:我知道这是解决这个特定问题的愚蠢方法;在现实世界的问题中,我有一个向量作为输入,我使用一些元素作为哈希图的键,该哈希图返回包含元素的计算结果]
我遇到的问题是我想在输出向量中引用输入向量内的元素。
在 MRE 中,我有一个
Vec<User>
作为输入,并有一个经过过滤的 Vec<User>
作为输出。理想情况下,我希望有一个 Vec<&User>
作为输出,只需引用输入元素,这样我就不必克隆它们(underage.push(el.clone());
)。
我相信我明白导致此问题的原因,但我能想到的唯一解决方案是将
Arc<Vec<Arc<User>>
作为输入传递,这看起来很糟糕。
有没有办法返回
Arc<Vec<&User>>
将向量内元素引用的生命周期与向量的生命周期连接起来?
谢谢!
use std::sync::Arc;
use std::sync::mpsc::channel;
use std::thread;
#[derive(Debug, Clone)]
struct User {
age: u32,
}
fn main() {
let my_vec: Vec<User> = vec!(
User{age: 10},
User{age: 20},
User{age: 15},
User{age: 18},
);
let arc_my_vec = Arc::new(my_vec);
// this is a thread that listens for work on a rx_work channel
// and puts the result of the work on a tx_result channel
let (tx_work, rx_work) = channel();
let (tx_result, rx_result) = channel();
let t = thread::spawn(move || {
loop {
let users: Arc<Vec<User>> = rx_work.recv().unwrap();
let mut underage = vec![];
for el in users.iter() {
if el.age < 18 {
underage.push(el.clone());
}
}
tx_result.send(underage).unwrap();
}
});
let this_vec = Arc::clone(&arc_my_vec);
// put work on the channel that's followed by the thread
tx_work.send(this_vec).unwrap();
// receive the result from the thread work
let underage = rx_result.recv().unwrap();
dbg!(underage);
t.join().unwrap();
}
尝试一下这里:
use std::sync::Arc;
use std::sync::mpsc::channel;
use std::thread;
#[derive(Debug)]
struct User {
age: u32,
}
fn main() {
let my_vec: Vec<User> = vec![
User { age: 10 },
User { age: 20 },
User { age: 15 },
User { age: 18 },
];
let arc_my_vec = Arc::new(my_vec);
// Specify the type of messages for the work channel
let (tx_work, rx_work): (std::sync::mpsc::Sender<Vec<usize>>, std::sync::mpsc::Receiver<Vec<usize>>) = channel();
let (tx_result, rx_result) = channel();
let arc_my_vec_clone = Arc::clone(&arc_my_vec);
let t = thread::spawn(move || {
while let Ok(indices) = rx_work.recv() {
let underage_indices: Vec<usize> = indices
.into_iter()
.filter(|&i| arc_my_vec_clone[i].age < 18)
.collect();
tx_result.send(underage_indices).unwrap();
}
});
// Send the indices of the vector to the worker thread
let indices: Vec<usize> = (0..arc_my_vec.len()).collect();
tx_work.send(indices).unwrap();
// Receive the result from the worker thread
let underage_indices = rx_result.recv().unwrap();
let underage_users: Vec<&User> = underage_indices
.iter()
.map(|&i| &arc_my_vec[i])
.collect();
dbg!(underage_users);
t.join().unwrap();
}