Rust异步并发请求报错:cannot return value referencing function parameter的解决
Rust异步并发请求的错误分析与解决
错误原因
你遇到的错误本质是异步函数生成的Future捕获了局部变量的引用,导致悬垂引用风险。虽然do_req最终返回的是独立的i32值,但异步函数的返回值是一个Future对象——这个对象会捕获调用时的环境,也就是对req的引用(因为do_req是&self方法)。
当map闭包执行完毕后,闭包内的req会被销毁,但生成的Future会一直存在到join_all执行,这就造成了引用指向已经被释放的内存,Rust的借用检查器直接拦截了这种不安全行为。
解决方法
方法1:让方法获取self的所有权
如果Request实例在调用do_req后无需保留,可以修改方法的接收者为self,将实例所有权转移到异步方法中,这样Future不再持有外部引用:
use std::time::Duration; use futures::future::join_all; use tokio::time::sleep; pub struct Request {} impl Request { // 将&self改为self,获取实例所有权 pub async fn do_req(self, num: i32) -> i32 { sleep(Duration::from_secs(1)).await; num * 2 } } #[tokio::test] async fn test() { let v = vec![Request{}, Request{}]; let futs: Vec<_> = v.into_iter().map(|req| req.do_req(1)).collect(); let res = join_all(futs).await; println!("{:?}", res); }
方法2:克隆Request实例
如果需要保留原Request实例,可为Request实现Clone trait,在闭包里克隆实例,让每个Future持有独立的克隆实例:
use std::time::Duration; use futures::future::join_all; use tokio::time::sleep; // 实现Clone trait #[derive(Clone, Debug)] pub struct Request {} impl Request { pub async fn do_req(&self, num: i32) -> i32 { sleep(Duration::from_secs(1)).await; num * 2 } } #[tokio::test] async fn test() { let v = vec![Request{}, Request{}]; let futs: Vec<_> = v.into_iter().map(|req| req.clone().do_req(1)).collect(); let res = join_all(futs).await; println!("{:?}", res); }
内容的提问来源于stack exchange,提问作者lemon
相关产品推荐
相关产品推荐

