这种情况经常发生在我身上,例如
pub struct EmailTemplateMessageBuilder(Translator);
impl EmailTemplateMessageBuilder {
pub fn new(locale: LanguageIdentifier) -> Self{
Self(Translator::new(locale))
}
fn render<C>(&self, template_name: &str, email_template: &EmailTemplate, context: &C) -> String {
let mut template_engine = TinyTemplate::new();
let translator = self.0;
//The add_formatter method below has signature:
// pub fn add_formatter<F>(&mut self, name: &'template str, formatter: F)
// where
// F: 'static + Fn(&Value, &mut String) -> Result<()>
template_engine.add_formatter(
"trans",
|value: &Value, output: &mut String| {
match value {
Value::String(s) => {
output.push_str(translator.trans_simple(s).as_ref());
Ok(())
}
_ => panic!("Unable to translate {}", value),
}
});
template_engine.render("default", context)
.expect(&format!("Enable to render email template {}", template_name))
}
}
由于EmailTemplateMessageBuilder结构拥有翻译器,我知道它的生存期比template_engine变量长,闭包也是如此,translator变量在被调用时应该始终有效。我似乎需要一种方法来将自己的引用转化为"静态生命"。
注:
- 翻译器无法实现Copy trait,因为它依赖于未复制的其他变量
- 此代码在同一个线程中运行,没有未来,没有多个线程
我似乎需要一种方法来将自己拥有的引用转换为"静态生存期"。
这就是Rc
的作用。将结构体定义为EmailTemplateMessageBuilder(Rc<Translator>)
,将translator
定义为self.0.clone()
。clone()
只克隆指针并增加引用计数,所以它很便宜。最后,将闭包设为move
,这样它就拥有所有捕获的数据。