Rust 返回一个Vec<&;str>;从参照单元格<;Vec<;字符串>>;?(或替代方法?)
所以我有一种数据库结构,它为我的应用程序存储数据。当数据变脏时,它会从数据库中获取数据并将其存储在结构中。无论哪种方式,当请求此数据时(Rust 返回一个Vec<&;str>;从参照单元格<;Vec<;字符串>>;?(或替代方法?),rust,Rust,所以我有一种数据库结构,它为我的应用程序存储数据。当数据变脏时,它会从数据库中获取数据并将其存储在结构中。无论哪种方式,当请求此数据时(Vec),我们将在数据库结构中的某个位置存储一个现有的字符串 从外部看,它应该看起来像这个数据库本身并没有发生变化,因为它应该看起来只是从数据库中获取数据。然而,在内部,它实际上存储了一些缓存,这样就不必在每一帧都获取数据。因此,我使用RefCell来存储缓存 好的,现在我应该能够得到一个Vec,其中&str引用了存储在数据库结构中的字符串 但是,不能保证此缓存
Vec
),我们将在数据库结构中的某个位置存储一个现有的字符串
从外部看,它应该看起来像这个数据库本身并没有发生变化,因为它应该看起来只是从数据库中获取数据。然而,在内部,它实际上存储了一些缓存,这样就不必在每一帧都获取数据。因此,我使用RefCell
来存储缓存
好的,现在我应该能够得到一个Vec
,其中&str
引用了存储在数据库结构中的字符串
但是,不能保证此缓存始终存在。例如,当数据无效时,需要再次获取数据。实际上,我们有一个RefCell
:
使用std::cell::RefCell;
结构连接{}
发布结构数据库{
db:连接,
项目\u缓存:RefCell,
// ...
}
不幸的是,我似乎无法做到这一点:
impl数据库{
发布fn项目(&self)->结果{
if self.projects\u cache.borrow()是\u some(){
让缓存:&Vec=&*self.projects\u cache.borrow().as\u ref().unwrap();
返回Ok(cached.iter().map(| name | name.as_str()).collect());
}
//如果没有,则从数据库获取数据并将其存储在缓存中
// ...
未执行!()
}
}
显然,这是一个临时值
错误[E0515]:无法返回引用临时值的值
-->src/lib.rs:15:20
|
14 |让缓存:&Vec=&*self.projects_cache.borrow().as_ref().unwrap();
|------------------------------此处创建的临时值
15 |返回Ok(cached.iter().map(| name | name.as_str()).collect());
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^返回引用当前函数拥有的数据的值
所以我的问题是:
为什么这个值是暂时的?字符串存在。我们只是想参考一下。那么为什么这是暂时的呢
我如何习惯性地做这件事?我一点也不喜欢这种方法。我所关心的是:我可以存储缓存;fetch函数接受&self
,从外部看是不可变的;而且,出于性能原因,我不必为每一帧制作全新的String
RefCell
可以通过共享引用进行变异,因为它执行运行时检查-通过内部跟踪对它的活动引用数(引用计数),确保没有使用任何其他引用
这是通过Ref
结构实现的-只要它存在,您就可以通过它读取RefCell
的内容。它的析构函数递减引用计数,通知RefCell
它将不再使用
这就是为什么您不能为用户提供对RefCell
内容的正常引用(&str
)-没有什么可以阻止它允许其内容发生变异。在这种情况下,字符串
将存在的承诺仅在Ref
在范围内时有效
但是,您可以将Ref
封装为实现细节。通过将Ref
包装在项目
类型中,您可以让用户与更简单的API交互:
pub结构项目);
impl项目谢谢你的建议-是的,但也不是。我以前看过这篇文章,但它没有让我满意。这个解决方案很难看,它让我觉得这不是最佳解决方案。我更感兴趣的是一种更惯用的方法可能是什么样子,不管它是否像这样使用RefCell
。上面的答案返回一些自定义结构,下一个返回一些Ref
struct。我想完全隐藏这个RefCell
实现,所以。最后,我还询问了为什么这个值被认为是临时的,但在这个线程中没有回答。我觉得您没有试图理解Ref
为什么在这里很重要。正如错误消息所示,Ref
是临时的(请注意,它在整个表达式self.projects\u cache.borrow()
下面加下划线)Ref
是RefCell
在运行时跟踪借用的方式。如果您可以返回Vec
,RefCell
将无法知道原始选项何时不再被借用(请注意,您实际上可以在夜间使用时安全地执行此操作,但这样做意味着您再也不能借用了)。谢谢!有没有更惯用的方法?尽管开销很大,但返回克隆是否更合适?理想情况下,我希望这在功能上等同于读取不可变结构的字段,就好像该字段一直存在一样。