Зачем нужна доставка статических переменных между методами, а не одним и тем же методом?
Я хочу запустить Hyper-сервер в функции с port
а также dao
параметры предоставлены main()
, но функция работает только после того, как я 'static
продолжительность жизни. Это меня сильно смутило.
extern crate futures;
extern crate hyper;
use futures::future::Future;
use hyper::header::ContentLength;
use hyper::server::{Http, Request, Response, Service};
use std::net::SocketAddr;
trait Dao {}
struct MysqlDao;
impl Dao for MysqlDao {}
struct HelloWorld<'a> {
dao: &'a Dao,
}
const PHRASE: &'static str = "Hello, World!";
impl<'a> Service for HelloWorld<'a> {
type Request = Request;
type Response = Response;
type Error = hyper::Error;
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
fn call(&self, _req: Request) -> Self::Future {
Box::new(futures::future::ok(
Response::new()
.with_header(ContentLength(PHRASE.len() as u64))
.with_body(PHRASE),
))
}
}
fn main() {
let addr = "127.0.0.1:3000".parse().unwrap();
let dao = MysqlDao;
let server = Http::new()
.bind(&addr, move || Ok(HelloWorld { dao: &dao }))
.unwrap();
server.run().unwrap();
}
Http::new().bind
Документация API говорит, что нужно NewService + 'static
так что я думаю, что компилятор выведет dao
вариант есть 'static
, но когда я убираю последние три утверждения из основного, это не может выводить!
fn main() {
let addr = "127.0.0.1:3000".parse().unwrap();
let dao: MysqlDao = MysqlDao;
web_startup(&addr, &dao);
}
fn web_startup<T: Dao>(addr: &SocketAddr, dao: &T) {
let server = Http::new()
.bind(addr, move || Ok(HelloWorld { dao }))
.unwrap();
server.run().unwrap();
}
Я получаю ошибку:
error[E0477]: the type `[closure@src/main.rs:44:21: 44:51 dao:&T]` does not fulfill the required lifetime
--> src/main.rs:44:10
|
44 | .bind(addr, move || Ok(HelloWorld { dao }))
| ^^^^
|
= note: type must satisfy the static lifetime
Итак, я исправил это:
fn main() {
let addr = "127.0.0.1:3000".parse().unwrap();
static DAO: MysqlDao = MysqlDao;
web_startup(&addr, &DAO);
}
fn web_startup<T: Dao>(addr: &SocketAddr, dao: &'static T) {
let server = Http::new()
.bind(addr, move || Ok(HelloWorld { dao }))
.unwrap();
server.run().unwrap();
}
Я не понимаю, почему я должен использовать static
ключевое слово для static DAO: MysqlDao = MysqlDao;
заявление, но не нужно, прежде чем изменить код. Компилятор не может сделать вывод, или я думаю о вещах неправильно?
1 ответ
Причина, по которой компилятор не может сделать вывод, что единственный раз web_startup
функция будет называться это вызывается с 'static
потому что это не гарантировано. Что, если функция была общедоступной и вызывалась сторонним модулем? Компилятор должен сказать конечному пользователю использовать 'static
на функции, которая, кажется, не требует таковой. Что делать, если какое-то время в будущем eval()
добавлен в Rust (например, для REPL), чтобы даже ваша частная функция могла быть вызвана с неожиданными параметрами функции?
Вы просите сделать вывод, которого не должно быть.