如何在处理程序之间传递变量

How can I pass around variables between handlers

我想要一个在所有处理程序中都可用的上下文结构,但我无法通过编译器获得。

举个例子,我想要这样的东西

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> <[closure@src\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));

这里的错误信息几乎无法理解(有一个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:8080").unwrap(); // port 80 is privileged
}

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

注意我把context的类型改成了&Context(否则闭包只会 FnOnce) and use move (the closure must have 'static lifetime to implement Handler)。

为了能够在 index 中更改 cache,您必须 change 将类型 Arc<Mutex<HashMap<String, String>>> 或类似。