Ich versuche Rust zu lernen, indem ich einen einfachen In-Memory URL-Shortener mit Hyper 0.10 implementiere. Ich laufe in ein Problem, das ich denke, wird verursacht, indem man versucht, eine veränderbare HashMap
in meinem Handler zu schließen über:Wie teile ich eine HashMap zwischen Hyper-Handlern?
fn post(mut req: Request, mut res: Response, short_uris: &mut HashMap<&str, &str>) {
let mut body = String::new();
match req.read_to_string(&mut body) {
Ok(_) => {
let key = short_uris.len();
short_uris.insert(&key.to_string(), &body.to_string());
*res.status_mut() = StatusCode::Created;
res.start().unwrap().write(&key.to_string().into_bytes());
},
Err(_) => *res.status_mut() = StatusCode::BadRequest
}
}
fn get(req: Request, mut res: Response, short_uris: &HashMap<&str, &str>) {
match req.uri.clone() {
AbsolutePath(path) => {
match short_uris.get::<str>(&path) {
Some(short_uri) => {
*res.status_mut() = StatusCode::MovedPermanently;
res.headers_mut().set(Location(short_uri.to_string()));
},
None => *res.status_mut() = StatusCode::NotFound
}
},
_ => *res.status_mut() = StatusCode::BadRequest
}
}
fn main() {
let mut short_uris: HashMap<&str, &str> = HashMap::new();
short_uris.insert("/example", "http://www.example.com");
Server::http("0.0.0.0:3001").unwrap().handle(move |req: Request, mut res: Response| {
match req.method {
hyper::Post => post(req, res, &mut short_uris),
hyper::Get => get(req, res, &short_uris),
_ => *res.status_mut() = StatusCode::MethodNotAllowed
}
}).unwrap();
}
src/main.rs:42:40: 42:46 error: the trait bound `for<'r, 'r, 'r> [[email protected]/main.rs:42:47: 48:3 short_uris:std::collections::HashMap<&str, &str>]: std::ops::Fn<(hyper::server::Request<'r, 'r>, hyper::server::Response<'r>)>` is not satisfied [E0277]
src/main.rs:42 Server::http("0.0.0.0:3001").unwrap().handle(move |req: Request, mut res: Response| {
Muss ich ein Arc
verwenden, um die HashMap
zwischen Threads zu teilen? Wenn ja, wie würde das aussehen? Außerdem könnte ich mich in Bezug auf das Problem völlig irren. Die Fehlermeldung ist für mich sehr kryptisch.
Warum deklarieren Sie die HashMap nicht als global? –
@ Dr.Sahib Ich versuche generell den globalen Zustand zu vermeiden. Außerdem habe ich den folgenden SO-Beitrag gelesen, der empfohlen hat, die Verwendung des globalen Status zu minimieren: http://stackoverflow.com/questions/27791532/how-do-i-create-a-global-mutable-singleton. Also habe ich versucht, es ohne globalen Staat zu machen. – forTruce
Nur, dass allnächtlich Rust gibt viel bessere Fehlermeldung hier: "erwartet eine Schließung, die das' Fn' Merkmal implementiert, aber diese Schließung implementiert nur 'FnMut'" – krdln