Rust 如何在互斥锁内的静态哈希映射中返回对项的引用?

Rust 如何在互斥锁内的静态哈希映射中返回对项的引用?,rust,lazy-static,Rust,Lazy Static,我试图访问静态hashmap进行读写,但总是出现错误: 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::ne

我试图访问静态hashmap进行读写,但总是出现错误:

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()
}
使用std::collections::HashMap;
使用std::sync::Mutex;
pub结构ModuleItem{
pub绝对路径:String,
}
懒惰的人!{
静态ref模块映射:Mutex=Mutex::new(HashMap::new());
}
发布fn插入(标识\u散列:i32,模块\u项:模块项){
模块映射
.lock()
.unwrap()
.插入(标识\u散列、模块\u项);
}
pub fn get(identity\u hash:i32)->选项
我试过使用.clone()、.clone()甚至什么都没试过,但都没能成功。你能帮我吗

克隆所做的一切就是克隆底层结构,在本例中,它是一个
&ModuleItem
,因此它只克隆引用,而您仍然有一个引用,您无法返回该引用,因为您只有在持有锁时才能访问hashmap的内容(否则它无法工作)

Option::cloned
实际上克隆了引用所持有的对象,但由于无法克隆ModuleItem,因此不会在此处编译

首先,您必须返回一个
选项
,您不能返回对映射内容的引用,因为锁将在函数结束时释放,并且您不能跨互斥体边界保留hashmap内容的句柄,因为它们可能随时消失(例如,其他线程可能会移动它们,甚至完全清除映射)

然后通过在
ModuleItem
上派生
Clone
(然后调用
Option::cloned
)或“手动”创建新的ModuleItem来复制ModuleItem,例如

pub-fn-get(identity\u hash:i32)->选项{
模块| MAP.lock().unwrap().get(&identity_hash).MAP(| m|
ModuleItem{absolute_path:m.absolute_path.clone()}
)
}
如果您经常需要
获取
密钥并担心性能,您可以随时存储
Arc
。这有一定的成本(因为它是一个指针,所以您的字符串现在位于两个指针后面),但是克隆弧非常便宜


为了避免双指针,您可以将
ModuleItem
设置为非大小类型,并让它存储
str
,但是。。。这很难使用,因此我不推荐使用。

函数
get
不能使用静态生存期,因为数据不会在程序的整个生存期内生存():

“作为引用生存期”static表示引用指向的数据在运行程序的整个生存期内都有效。它仍然可以被强制缩短寿命

因此,您必须返回非静态引用或
HashMap
值的副本。引用不可能,因为返回一个
MutexGuard
,它是一个本地变量,因此是一个临时变量,保存
HashMap
。和
HashMap
get()
返回一个引用

由于临时
MutexGuard
将在函数结束时销毁,因此
get
返回的引用将指向临时值

要解决此问题,可以使
ModuleItem
clonable并返回值的副本:

使用std::collections::HashMap;
使用std::sync::Mutex;
#[衍生(克隆)]
pub结构ModuleItem{
pub绝对路径:String,
}
懒惰的静态::懒惰的静态!{
静态ref模块映射:Mutex=Mutex::new(HashMap::new());
}
发布fn插入(标识\u散列:i32,模块\u项:模块项){
模块映射
.lock()
.unwrap()
.插入(标识\u散列、模块\u项);
}
pub fn get(identity\u hash:i32)->选项{
模块_MAP.lock().unwrap().get(&identity_hash).cloned()
}

Thx查看两个答案。两者似乎都有效。它们之间的区别是什么?在另一个答案中,您必须通过
map
功能手动复制数据。在我的回答中,复制是通过从
Clone
派生并使用
Clone
方法完成的