Rust报错cannot move out of an `Arc`,调用Routing的get_route方法如何解决?
问题根源
你的get_route和get_relevant_map方法的第一个参数使用了值语义的self,调用时会消耗Routing实例的所有权。但你的Routing实例被包裹在Arc中共享,Arc不允许你将内部的值移出(除非你是唯一持有者,显然多线程处理请求的场景下不满足这个条件),因此触发了E0507错误。
最优解决方案(推荐)
直接修改Routing的方法签名,使用不可变引用&self代替所有权转移的self,你的两个方法本质都是只读操作,完全不需要消耗实例:
impl Routing { // 其余方法保持不变 #[inline(always)] // 修改参数为&self,对应的成员clone后返回即可 fn get_relevant_map(&self, route: &Method) -> Option<Node<PyFunction>> { match route { &Method::GET => Some(self.get_routes.clone()), &Method::POST => Some(self.post_routes.clone()), &Method::PUT => Some(self.put_routes.clone()), &Method::PATCH => Some(self.patch_routes.clone()), &Method::DELETE => Some(self.delete_routes.clone()), &Method::HEAD => Some(self.head_routes.clone()), &Method::OPTIONS => Some(self.options_routes.clone()), &Method::CONNECT => Some(self.connect_routes.clone()), &Method::TRACE => Some(self.trace_routes.clone()), _ => None, } } #[inline(always)] // 同样修改参数为&self pub fn get_route(&self, route_method: &Method, route: &str) -> Option<PyFunction> { println!("Hello world how are your"); let table = self.get_relevant_map(route_method)?; match table.at(route) { Ok(res) => Some(res.value.clone()), Err(_) => None, } } }
修改后调用逻辑可以直接简化为:
async fn index( router: web::Data<Arc<Routing>>, headers: web::Data<Arc<Headers>>, mut payload: web::Payload, req: HttpRequest, ) -> impl Responder { match router.get_route(req.method(), req.uri().path()) { Some(handler_function) => { return handle_request(&handler_function, &headers, &mut payload, &req).await } None => { let mut response = HttpResponse::Ok(); apply_headers(&mut response, &headers); return response.finish(); } } }
替代解决方案(无需修改Routing定义)
如果你不方便改动Routing结构体的方法实现,可以手动克隆一份Arc内部的Routing实例,消耗克隆出来的独立实例即可:
async fn index( router: web::Data<Arc<Routing>>, headers: web::Data<Arc<Headers>>, mut payload: web::Payload, req: HttpRequest, ) -> impl Responder { // 克隆出独立的Routing实例,调用方法时消耗克隆的实例,不影响原Arc中的共享数据 let routing_clone = router.as_ref().clone(); match routing_clone.get_route(req.method(), req.uri().path()) { Some(handler_function) => { return handle_request(&handler_function, &headers, &mut payload, &req).await } None => { let mut response = HttpResponse::Ok(); apply_headers(&mut response, &headers); return response.finish(); } } }
内容的提问来源于stack exchange,提问作者Sanskar Jethi
相关产品推荐
相关产品推荐

