2016-08-12 16 views
3

Я хочу иметь структуру контекста, которая доступна во всех обработчиках, но я не могу получить корыта компилятора.Как передать переменные между обработчиками

Для примера, я хочу что-то вроде этого

extern crate iron; 
extern crate router; 

use iron::prelude::*; 
use router::Router; 
use std::collections::HashMap; 

struct Context { 
    cache: HashMap<String, String>, 
} 

fn main() { 
    let mut context = Context { cache: HashMap::new(), }; 
    let mut router = Router::new(); 

    router.get("/", |request| index(request, context)); 

    Iron::new(router).http("localhost:80").unwrap(); 
} 


fn index(_: &mut Request, context: Context) -> IronResult<Response> { 
    Ok(Response::with((iron::status::Ok, "index"))) 
} 

это не будет компилировать с сообщением об ошибке длительной

error: type mismatch resolving `for<'r, 'r, 'r> <[[email protected]\main.rs:... context:_] as std::ops::FnOnce<(&'r mut iron::Request<'r, 'r>,)>>::Output == std::result::Result<iron::Response, iron::IronError>`: 
expected bound lifetime parameter , 
    found concrete lifetime [E0271] 
src\main.rs:...  router.get("/", |request| index(request, context)); 

ответ

4

Сообщение об ошибке почти непостижимо здесь (есть issue для Это!).

Проблема в том, что тип замыкания не выводится. Мы можем помочь компилятору аннотирования типа request:

extern crate iron; 
extern crate router; 

use iron::prelude::*; 
use router::Router; 
use std::collections::HashMap; 
use std::sync::{Arc, Mutex}; 

#[derive(Clone, Default)] 
struct Context { 
    cache: Arc<Mutex<HashMap<String, String>>>, 
} 

fn main() { 
    let context = Context::default(); 
    let mut router = Router::new(); 

    let c = context.clone(); 
    router.get("/", move |request: &mut Request| index(request, &c), "index"); 

    Iron::new(router).http("localhost:80").unwrap(); 
} 

fn index(_: &mut Request, context: &Context) -> IronResult<Response> { 
    Ok(Response::with((iron::status::Ok, "index"))) 
} 

Обратите внимание, что я изменил тип context к &Context (в противном случае, закрытие будет только implementsFnOnce) и использовать move (замыкание должно быть 'static жизней для реализации Handler).

Чтобы сделать возможным изменение cache в index, вы должны change типа для Arc<Mutex<HashMap<String, String>>> или аналогичный.

+0

Большое спасибо за это. Теперь я не указал это в своей первоначальной проблеме, но у меня есть более одной из этих router.get-строк (это точка использования маршрутизатора) и добавления второй строки (router.get ("/ hi" , move | ... | hi (...));) приведет к новым ошибкам компилятора. ошибка: захват перемещенного значения: 'context' – Nozdrum

+0

@Nozdrum См. обновление. – malbarbo

+0

Снова большое спасибо за это. Здесь я не понимаю (почему мне нужно клонировать все, когда содержание структуры будет одинаковым, почему мне нужно «переместить» мое закрытие и что это значит, почему это происходит? в моей структуре). Я прочитал книгу/книгу о ржавчине и теперь просто понимаю, что я действительно не понимаю, что они там написали. – Nozdrum