我正在尝试访问静态哈希图进行读写,但我总是收到错误:
use std::collections::HashMap;
use std::sync::Mutex;
pub struct ModuleItem {
pub absolute_path: String,
}
lazy_static! {
static ref MODULE_MAP: Mutex<HashMap<i32, ModuleItem>> = Mutex::new(HashMap::new());
}
pub fn insert(identity_hash: i32, module_item: ModuleItem) {
MODULE_MAP
.lock()
.unwrap()
.insert(identity_hash, module_item);
}
pub fn get(identity_hash: i32) -> Option<&'static ModuleItem> {
MODULE_MAP.lock().unwrap().get(&identity_hash).clone()
}
但是我在获取函数cannot return value referencing temporary value
上收到错误
我尝试了.cloned()
,.clone()
甚至什么都没有,但我无法让它工作。你可以帮我吗?
我尝试使用.cloned((,.clone((甚至什么都没有,但我无法让它工作。你可以帮我吗?
Option::clone
所做的只是克隆底层结构,在这种情况下,这是一个&ModuleItem
,所以它只是克隆引用,你仍然有一个引用,你不能返回,因为你只能在持有锁时访问哈希映射的内容(否则它不起作用(。
Option::cloned
实际上克隆了通过引用保存的对象,但在此处不编译,因为无法克隆 ModuleItem。
首先你必须返回一个Option<ModuleItem>
,你不能返回对映射内容的引用,因为锁将在函数结束时释放,并且你不能跨互斥体边界保留哈希图内容的句柄,因为它们可能随时消失(例如,另一个线程可以移动它们, 甚至完全清除地图(。
然后复制模块项,方法是在ModuleItem
上派生Clone
(然后调用Option::cloned
(或通过"手动"创建一个新的模块项,例如
pub fn get(identity_hash: i32) -> Option<ModuleItem> {
MODULE_MAP.lock().unwrap().get(&identity_hash).map(|m|
ModuleItem { absolute_path: m.absolute_path.clone() }
)
}
如果您需要经常get
钥匙并且担心性能,您可以随时存储Arc<ModuleItem>
。这有一些成本(因为它是一个指针,所以你的字符串现在在两个指针后面(,但是克隆 Arc 非常便宜。
为了避免双指针,您可以将ModuleItem
变成未调整大小的类型,并让它存储一个str
但是......这很难使用,所以我不推荐它。
函数get
不能使用静态生存期,因为数据不会在程序的整个生命周期内存在(来自 Rust 书(:
作为引用生存期,"static "表示引用指向的数据在正在运行的程序的整个生存期内存在。它仍然可以被胁迫到更短的寿命。
因此,您必须返回非静态引用或HashMap
值的副本。引用是不可能的,因为MODULE_MAP.lock().unwrap()
返回一个MutexGuard
,该是一个局部变量,因此是一个保存HashMap
的临时变量。get()
HashMap
返回引用。
由于临时MutexGuard
将在函数结束时销毁,因此get
返回的引用将指向临时值。
要解决此问题,您可以使ModuleItem
可克隆并返回该值的副本:
use std::collections::HashMap;
use std::sync::Mutex;
#[derive(Clone)]
pub struct ModuleItem {
pub absolute_path: String,
}
lazy_static::lazy_static! {
static ref MODULE_MAP: Mutex<HashMap<i32, ModuleItem>> = Mutex::new(HashMap::new());
}
pub fn insert(identity_hash: i32, module_item: ModuleItem) {
MODULE_MAP
.lock()
.unwrap()
.insert(identity_hash, module_item);
}
pub fn get(identity_hash: i32) -> Option<ModuleItem> {
MODULE_MAP.lock().unwrap().get(&identity_hash).cloned()
}