借来的价值在Tokio的未来中无法长期生存

时间:2019-04-10 10:44:51

标签: rust borrow-checker rust-tokio

我正在尝试使用Rust和tokio编写一个简单的HTTP服务器。

一切正常,直到我想发送响应为止。

代码如下:

use std::fs;
use std::sync::Arc;
use tokio::net::TcpListener; // 0.1.15
use tokio::prelude::*;

fn main() {
    let addr = "0.0.0.0:8080".parse().unwrap();
    let listener = TcpListener::bind(&addr).expect("unable to bind TCP listener");

    let incoming = listener.incoming();

    let server = incoming
        .map_err(|e| eprintln!("accept failed = {:?}", e))
        .for_each(|socket| {
            println!(
                "Connection established: from {:?} to {:?}",
                socket.peer_addr(),
                socket.local_addr()
            );
            let bytes = vec![0; 512];
            let processor = tokio::io::read(socket, bytes)
                .and_then(|(socket, bytes, _size)| {
                    println!("Request: {}", String::from_utf8_lossy(&bytes[..]));
                    let contents = fs::read_to_string("hello.html").unwrap();
                    let response = Arc::new(format!("HTTP/1.1 200 OK\r\n\r\n{}", contents));
                    let response = response.clone();
                    tokio::io::write_all(socket, response.as_bytes()).and_then(|_| Ok(()))
                })
                .map_err(|_| ());
            tokio::spawn(processor);
            Ok(())
        });

    tokio::run(server);
}
error[E0597]: `response` does not live long enough
  --> src/main.rs:27:50
   |
27 |                     tokio::io::write_all(socket, response.as_bytes()).and_then(|_| Ok(()))
   |                                                  ^^^^^^^^ borrowed value does not live long enough
28 |                 })
   |                 - `response` dropped here while still borrowed

我该如何声明响应以使生命足够长?

1 个答案:

答案 0 :(得分:1)

如何使它工作?

正如我在评论中指出的那样:使用into_bytes,而不是用Arc包装并传递借来的字节数组。

Playground


@David:

  

但是我不明白为什么不使用弧线包裹。

Arc计算内部对象的引用:

  • 当您clone()
  • 时,它会增加引用
  • Arc所有者被删除时,它会减少引用。
  • 当引用计数减少到 0
  • 时,它会从内存中删除

在您的情况下,名为Arc的{​​{1}}的所有者。 response在作用域中创建,并在相同作用域的末尾删除。创建时它的引用计数为1,删除后为0。但是,您已经在response内将Arc的引用传递到内存中之前。

请注意,Future创建了一个write_all(),并且Future带有您的Future的引用,该引用在Arc被删除之前已从内存中删除。执行。

注释Future可以拥有借入已移动值的所有权,它希望可以将其转换为通用参数WriteAll