首页 > 解决方案 > 如果我在代码的不同位置使用非可变变量,为什么会出现借用错误?

问题描述

我正在学习 rust,我正在努力理解为什么以下代码无法编译,并在 req.into_body() 上出现一些“错误 [E0505]:无法移出,req因为它是借用的”错误。如果我删除 println! 或在比赛前移动它,它会运行。

async fn hello_world(req: Request<Body>) -> Result<Response<Body>, Infallible> {
  let mut response = Response::new(Body::empty());

  let method = req.method();
  let path = req.uri().path();

  match (method, path) {
    (&Method::GET, "/") => {
      *response.body_mut() = Body::from("Try POSTing data to /echo");
    }
    (&Method::POST, "/echo") => {
      *response.body_mut() = req.into_body();
    }
    _ => {
      *response.status_mut() = StatusCode::NOT_FOUND;
    }
  };
  println!("{} {}", method, path);

  Ok(response)
}

我理解一些借用,但我不明白为什么 println 的位置会发生任何变化,因为我已经定义了在匹配中成功使用的非可变变量。

标签: rustborrow-checker

解决方案


您不能同时拥有可变和不可变借用。对于您的情况,将借用类型(method()和的返回uri().path())转换为拥有的类型。您可以通过ToOwned::to_owned或通过显式转换(操场)来做到这一点:

async fn hello_world(req: Request<Body>) -> Result<Response<Body>, Infallible> {
    let mut response = Response::new(Body::empty());

    let method = req.method().clone(); // &Method -> Method
    let path = req.uri().path().to_string(); // &str -> String
    // `req` is not borrowed at this point, so it can be mutated

    match (method.clone(), path.as_str()) {
        (Method::GET, "/") => {
            *response.body_mut() = Body::from("Try POSTing data to /echo");
        }
        (Method::POST, "/echo") => {
            *response.body_mut() = req.into_body();
        }
        _ => {
            *response.status_mut() = StatusCode::NOT_FOUND;
        }
    };
    println!("{} {}", method, path);

    Ok(response)
}

推荐阅读