面试题答案
一键面试use std::collections::HashMap;
use tokio::sync::mpsc;
use tokio::task;
// 模拟网络请求函数
async fn mock_network_request(url: &str) -> Result<String, String> {
// 这里简单返回一个固定结果,实际应用中会是真正的网络请求
if url.contains("success") {
Ok(format!("Data from {}", url))
} else {
Err(format!("Failed to fetch from {}", url))
}
}
// 处理单个请求返回数据的函数
fn process_response(response: String) -> Vec<String> {
// 这里简单模拟根据特定条件循环处理数据
let mut result = Vec::new();
for _ in 0..3 {
result.push(response.clone());
}
result
}
#[tokio::main]
async fn main() {
// 定义要请求的URL列表
let urls = vec![
"http://example.com/success1",
"http://example.com/failure",
"http://example.com/success2",
];
// 创建一个通道用于发送处理结果
let (tx, mut rx) = mpsc::channel(10);
// 并发处理每个网络请求
for url in urls {
let tx_clone = tx.clone();
task::spawn(async move {
match mock_network_request(url).await {
Ok(response) => {
let processed = process_response(response);
for item in processed {
if let Err(e) = tx_clone.send(item).await {
eprintln!("Failed to send item: {}", e);
}
}
}
Err(e) => {
eprintln!("Request failed: {}", e);
}
}
});
}
// 收集并处理所有结果
let mut all_results = Vec::new();
while let Some(result) = rx.recv().await {
all_results.push(result);
}
println!("All processed results: {:?}", all_results);
}
代码解释
-
模拟网络请求函数
mock_network_request
:- 这个函数模拟了实际的网络请求。它接受一个
url
字符串作为参数。 - 根据
url
是否包含 "success" 来决定返回成功结果还是失败结果,返回值类型是Result<String, String>
,Ok
代表成功,Err
代表失败。
- 这个函数模拟了实际的网络请求。它接受一个
-
处理单个请求返回数据的函数
process_response
:- 这个函数接受一个
response
字符串作为参数,模拟根据特定条件对返回数据进行循环处理。 - 这里简单地将传入的
response
克隆三次并放入一个Vec<String>
中返回。
- 这个函数接受一个
-
主函数
main
:- 定义URL列表:
let urls = vec!["http://example.com/success1", "http://example.com/failure", "http://example.com/success2"];
定义了要请求的URL列表。 - 创建通道:
let (tx, mut rx) = mpsc::channel(10);
创建了一个mpsc
(多生产者 - 单消费者)通道,用于在不同任务间传递处理结果,通道容量为10。 - 并发处理请求:
- 使用
for
循环遍历urls
列表。 - 在每次循环中,克隆一个
tx
(发送端),然后使用task::spawn
创建一个新的异步任务。 - 在每个任务中,调用
mock_network_request
进行网络请求,并通过match
处理请求结果。 - 如果请求成功,调用
process_response
处理响应数据,并通过通道tx_clone
将处理后的结果发送出去。如果发送失败,打印错误信息。 - 如果请求失败,打印失败信息。
- 使用
- 收集并处理结果:
- 使用
while let
循环从通道rx
(接收端)接收数据。 - 每次接收到数据,将其放入
all_results
向量中。 - 最后打印所有处理后的结果。
- 使用
- 定义URL列表:
异步控制流和循环概念
- 异步控制流:
- 使用
task::spawn
创建多个并发的异步任务,每个任务独立执行网络请求。 - 通过
await
暂停任务执行,等待异步操作(如网络请求)完成,避免阻塞线程,提高并发性能。 - 使用
mpsc
通道在不同任务间传递数据,实现任务间的通信和同步。
- 使用
- 循环概念:
- 在
process_response
函数中,使用for
循环模拟对单个请求返回数据的特定条件循环处理。 - 在主函数中,使用
for
循环遍历URL列表,启动多个并发任务处理每个URL的请求。 - 使用
while let
循环从通道接收数据,直到通道关闭,实现对所有任务处理结果的收集。
- 在