Решение довольно простое, правда. Поскольку вам понадобится структура, которая позволит вам получить изменяемый заем по требованию, вам понадобится RwLock
. И поскольку я предполагаю, что вы строите HTTP-маршрутизатор, чтобы обойти требования времени жизни на Foo
, вы захотите обернуть это RwLock
в Arc
, вот так:
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
struct Foo(bool);
impl Foo {
fn say(&self) {
println!("I'm {}", self.0);
}
fn morph(&mut self) {
self.0 = !self.0;
}
}
fn main() {
let mut foo = Arc::new(RwLock::new(Foo(true)));
let mut routes: HashMap<String, Box<FnMut()>> = HashMap::new();
routes.insert("foo/say".to_string(), Box::new(|| foo.read().unwrap().say())); //< First (immutable) borrow of foo
routes.insert("foo/morph".to_string(), Box::new(|| foo.write().unwrap().morph())); //< Second (mutable) borrow of foo
routes.insert("bar".to_string(), Box::new(|| println!("hello"))); //< Compiler also says immutable foo is used here
}
Обратите внимание, что я злоупотребил тем, что все может просто заимствовать foo
только для чтения для этого. Если вам когда-либо понадобится move
вещи в замыканиях, Arc
реализует Clone
, поэтому вам определенно следует воспользоваться этим.
В остальном все в порядке - если у всех замыканий одинаковая подписьупаковывать их и хранить в любой коллекции - идиоматизм.