如何用人造丝遍历数组?
How to iterate over an array with rayon?
我是 Rust 的新手,我正在尝试使用人造丝从一组 URL 中获取响应
use rayon::prelude::*;
use reqwest::*;
fn main() -> Result<()> {
let urls = vec!["https://example.com"];
urls.par_iter().for_each(|url: &&str| -> Result<()> {
println!("Hello... {:?}", url);
let resp = reqwest::blocking::get(url)?.text()?;
println!("{:#?}", resp);
Ok(())
});
Ok(())
}
但是我收到了这个错误
error[E0271]: type mismatch resolving `<[closure@src\main.rs:252:30: 257:6] as FnOnce<(&&str,)>>::Output == ()`
--> src\main.rs:252:21
|
252 | urls.par_iter().for_each(|url| -> Result<()> {
| ^^^^^^^^ expected enum `std::result::Result`, found `()`
|
= note: expected enum `std::result::Result<(), reqwest::Error>`
found unit type `()`
error[E0277]: the trait bound `&&str: IntoUrl` is not satisfied
--> src\main.rs:254:20
|
254 | let resp = reqwest::blocking::get(url)?.text()?;
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoUrl` is not implemented for `&&str`
|
::: mod.rs:106:15
|
106 | pub fn get<T: crate::IntoUrl>(url: T) -> crate::Result<Response> {
| -------------- required by this bound in `reqwest::blocking::get`
|
= help: the following implementations were found:
<&'a str as IntoUrl>
for_each
取 closure/lambda 其 return 类型是 unit
而不是 Result
?
运算符不能在函数内部使用 /closure/lambda which return unit -> ()
*
用于取消引用和访问底层字符串
src/main.rs
use rayon::prelude::*;
fn main() {
let urls = vec!["https://example.com"];
urls.par_iter().for_each(|url: &&str| {
println!("Hello... {:?}", *url);
let resp = reqwest::blocking::get(*url).unwrap().text();
println!("{:#?}", resp);
});
}
Cargo.toml
[package]
name = "s71275260"
version = "0.1.0"
edition = "2021"
# see more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rayon = "1.5.1"
reqwest = { version = "0.11", features = ["blocking"] }
第二个错误更容易:IntoUrl
没有为 &&str
实现,而是为 &str
实现。所以你需要做的就是取消引用指针:
urls.par_iter().for_each(|url: &&str| -> Result<()> {
let url = *url;
或者
urls.par_iter().for_each(|&url: &&str| -> Result<()> {
第一个比较棘手。问题是 for_each()
需要一个 returns ()
的闭包,并给它一个 returns Result
不起作用的闭包。
因为您希望在请求失败时继续处理其他请求,所以您不能使用 rayon 的 try_for_each()
,因为它会在失败时停止所有待处理的请求。相反,您只想忽略失败,也许将其记录下来。使用 unwrap()
是个坏主意:它不仅会停止其他请求,还会中止您的程序! 从不 使用 unwrap()
,除非您 100% 确定代码永远不会失败(如果它不明显,最好注释为什么)。您可以放弃 ?
运算符,而只是显式:
urls.par_iter().for_each(|&url| {
println!("Hello... {:?}", url);
if let Ok(resp) = reqwest::blocking::get(url) {
if let Ok(resp) = resp.text() {
println!("{:#?}", resp);
}
}
});
虽然您可以稍微改进一下这段代码,但它仍然很难看。 try
blocks 会改善这种情况;在它们稳定下来之前,对于具有多个潜在故障点的块有一个常见的习语:
urls.par_iter().for_each(|&url| {
_ = (|| -> Result<()> {
println!("Hello... {:?}", url);
let resp = reqwest::blocking::get(url)?.text()?;
println!("{:#?}", resp);
Ok(())
})();
});
这利用闭包的能力来使用 ?
运算符来简化代码。
但是请注意 rayon
不适用于 IO-bound 任务:使用像 tokio
.
这样的异步框架
我是 Rust 的新手,我正在尝试使用人造丝从一组 URL 中获取响应
use rayon::prelude::*;
use reqwest::*;
fn main() -> Result<()> {
let urls = vec!["https://example.com"];
urls.par_iter().for_each(|url: &&str| -> Result<()> {
println!("Hello... {:?}", url);
let resp = reqwest::blocking::get(url)?.text()?;
println!("{:#?}", resp);
Ok(())
});
Ok(())
}
但是我收到了这个错误
error[E0271]: type mismatch resolving `<[closure@src\main.rs:252:30: 257:6] as FnOnce<(&&str,)>>::Output == ()`
--> src\main.rs:252:21
|
252 | urls.par_iter().for_each(|url| -> Result<()> {
| ^^^^^^^^ expected enum `std::result::Result`, found `()`
|
= note: expected enum `std::result::Result<(), reqwest::Error>`
found unit type `()`
error[E0277]: the trait bound `&&str: IntoUrl` is not satisfied
--> src\main.rs:254:20
|
254 | let resp = reqwest::blocking::get(url)?.text()?;
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoUrl` is not implemented for `&&str`
|
::: mod.rs:106:15
|
106 | pub fn get<T: crate::IntoUrl>(url: T) -> crate::Result<Response> {
| -------------- required by this bound in `reqwest::blocking::get`
|
= help: the following implementations were found:
<&'a str as IntoUrl>
for_each
取 closure/lambda 其 return 类型是 unit
而不是 Result
?
运算符不能在函数内部使用 /closure/lambda which return unit -> ()
*
用于取消引用和访问底层字符串
src/main.rs
use rayon::prelude::*;
fn main() {
let urls = vec!["https://example.com"];
urls.par_iter().for_each(|url: &&str| {
println!("Hello... {:?}", *url);
let resp = reqwest::blocking::get(*url).unwrap().text();
println!("{:#?}", resp);
});
}
Cargo.toml
[package]
name = "s71275260"
version = "0.1.0"
edition = "2021"
# see more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rayon = "1.5.1"
reqwest = { version = "0.11", features = ["blocking"] }
第二个错误更容易:IntoUrl
没有为 &&str
实现,而是为 &str
实现。所以你需要做的就是取消引用指针:
urls.par_iter().for_each(|url: &&str| -> Result<()> {
let url = *url;
或者
urls.par_iter().for_each(|&url: &&str| -> Result<()> {
第一个比较棘手。问题是 for_each()
需要一个 returns ()
的闭包,并给它一个 returns Result
不起作用的闭包。
因为您希望在请求失败时继续处理其他请求,所以您不能使用 rayon 的 try_for_each()
,因为它会在失败时停止所有待处理的请求。相反,您只想忽略失败,也许将其记录下来。使用 unwrap()
是个坏主意:它不仅会停止其他请求,还会中止您的程序! 从不 使用 unwrap()
,除非您 100% 确定代码永远不会失败(如果它不明显,最好注释为什么)。您可以放弃 ?
运算符,而只是显式:
urls.par_iter().for_each(|&url| {
println!("Hello... {:?}", url);
if let Ok(resp) = reqwest::blocking::get(url) {
if let Ok(resp) = resp.text() {
println!("{:#?}", resp);
}
}
});
虽然您可以稍微改进一下这段代码,但它仍然很难看。 try
blocks 会改善这种情况;在它们稳定下来之前,对于具有多个潜在故障点的块有一个常见的习语:
urls.par_iter().for_each(|&url| {
_ = (|| -> Result<()> {
println!("Hello... {:?}", url);
let resp = reqwest::blocking::get(url)?.text()?;
println!("{:#?}", resp);
Ok(())
})();
});
这利用闭包的能力来使用 ?
运算符来简化代码。
但是请注意 rayon
不适用于 IO-bound 任务:使用像 tokio
.