如何解决具有自有值的 Rust 块方法?
我试图一次对多个字符串块执行并行操作,但我发现借用检查器存在问题:
(对于上下文,identifiers
是来自 CSV 文件的 Vec<String>
,client
是 reqwest,而 target
是 Arc<String>
,一次写入多次读取)
use futures::{stream,StreamExt};
use std::sync::Arc;
async fn nop(
person_ids: &[String],target: &str,url: &str,) -> String {
let noop = format!("{} {}",target,url);
let noop2 = person_ids.iter().for_each(|f| {f.as_str();});
"Some text".into()
}
#[tokio::main]
async fn main() {
let target = Arc::new(String::from("sometext"));
let url = "http://example.com";
let identifiers = vec!["foo".into(),"bar".into(),"baz".into(),"qux".into(),"quux".into(),"quuz".into(),"corge".into(),"grault".into(),"garply".into(),"waldo".into(),"fred".into(),"plugh".into(),"xyzzy".into()];
let id_sets: Vec<&[String]> = identifiers.chunks(2).collect();
let responses = stream::iter(id_sets)
.map(|person_ids| {
let target = target.clone();
tokio::spawn( async move {
let resptext = nop(person_ids,target.as_str(),url).await;
})
})
.buffer_unordered(2);
responses
.for_each(|b| async { })
.await;
}
给定块产生 Vec,编译器抱怨 identifiers
的寿命不够长,因为它可能在切片被引用时超出范围。实际上这不会发生,因为有一个等待。有没有办法告诉编译器这是安全的,还是有另一种方法可以将块作为每个线程的一组拥有的字符串获取?
有一个类似的问题,使用 into_owned() 作为解决方案,但是当我尝试这样做时,rustc 抱怨在 request_user 函数中编译时不知道切片大小。
编辑:还有一些其他问题:
-
是否有更直接的方式在每个线程中使用
target
而不需要 Arc?从它创建的那一刻起,它就不需要修改,只需读取即可。如果没有,是否有一种不需要 .as_str() 方法就可以将其从 Arc 中拉出的方法? -
您如何处理 tokio::spawn() 块中的多种错误类型?在实际使用中,我将在其中收到 quick_xml::Error 和 reqwest::Error 。它在没有 tokio spawn 的情况下运行良好。
解决方法
您的问题是标识符是对切片的引用向量。一旦您离开函数的作用域,它们就不一定会出现(这就是里面的异步移动会做的事情)。
解决当前问题的方法是将 Vec<&[String]>
转换为 Vec<Vec<String>>
类型。
实现这一目标的方法是:
let id_sets: Vec<Vec<String>> = identifiers
.chunks(2)
.map(|x: &[String]| x.to_vec())
.collect();
,
有没有办法告诉编译器这是安全的,或者有没有另一种方法将块作为每个线程的一组拥有的字符串获取?
您可以使用 Vec<T>
crate 将 Vec<Vec<T>>
分块到 itertools
而无需克隆:
use itertools::Itertools;
fn main() {
let items = vec![
String::from("foo"),String::from("bar"),String::from("baz"),];
let chunked_items: Vec<Vec<String>> = items
.into_iter()
.chunks(2)
.into_iter()
.map(|chunk| chunk.collect())
.collect();
for chunk in chunked_items {
println!("{:?}",chunk);
}
}
["foo","bar"]
["baz"]
这是基于答案 here。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。