我尝试使用函数作为值创建HashMap
:
#[macro_use]
extern crate lazy_static;
use std::collections::HashMap;
lazy_static! {
static ref HASHES: HashMap<&'static str, &'static Fn([u8])> = {
let mut m = HashMap::new();
m.insert("md5", &md5);
m
};
}
fn md5(bytes: &[u8]) -> String {
String::default()
}
编译器给出了一个错误:
error[E0277]: the trait bound `std::ops::Fn([u8]) + 'static: std::marker::Sync` is not satisfied in `&'static std::ops::Fn([u8]) + 'static`
--> src/main.rs:6:1
|
6 | lazy_static! {
| _^ starting here...
7 | | static ref HASHES: HashMap<&'static str, &'static Fn([u8])> = {
8 | | let mut m = HashMap::new();
9 | | m.insert("md5", &md5);
10 | | m
11 | | };
12 | | }
| |_^ ...ending here: within `&'static std::ops::Fn([u8]) + 'static`, the trait `std::marker::Sync` is not implemented for `std::ops::Fn([u8]) + 'static`
|
= note: `std::ops::Fn([u8]) + 'static` cannot be shared between threads safely
= note: required because it appears within the type `&'static std::ops::Fn([u8]) + 'static`
= note: required because of the requirements on the impl of `std::marker::Sync` for `std::collections::hash::table::RawTable<&'static str, &'static std::ops::Fn([u8]) + 'static>`
= note: required because it appears within the type `std::collections::HashMap<&'static str, &'static std::ops::Fn([u8]) + 'static>`
= note: required by `lazy_static::lazy::Lazy`
= note: this error originates in a macro outside of the current crate
我不明白我该怎么做才能解决这个错误,而且我也不知道如何创建这样的HashMap
。
答案 0 :(得分:8)
您的代码有多个问题。编译器提供的错误告诉您,您的代码将使内存不安全:
`std::ops::Fn([u8]) + 'static` cannot be shared between threads safely
您在HashMap
中存储的类型无法保证可以共享。
你可以修复&#34;通过将值类型更改为&'static (Fn([u8]) + Sync)
来指定此类限制。这会解锁下一个错误,因为您的功能签名不匹配:
expected type `std::collections::HashMap<&'static str, &'static std::ops::Fn([u8]) + std::marker::Sync + 'static>`
found type `std::collections::HashMap<&str, &fn(&[u8]) -> std::string::String {md5}>`
&#34;定影&#34;使用&'static (Fn(&[u8]) -> String + Sync)
会导致更深奥的生命周期错误:
expected type `std::collections::HashMap<&'static str, &'static for<'r> std::ops::Fn(&'r [u8]) -> std::string::String + std::marker::Sync + 'static>`
found type `std::collections::HashMap<&str, &fn(&[u8]) -> std::string::String {md5}>`
可以&#34;修复&#34;通过使用&md5 as &'static (Fn(&[u8]) -> String + Sync))
转换函数,这将导致
note: borrowed value must be valid for the static lifetime...
note: consider using a `let` binding to increase its lifetime
这是因为the reference you've made is to a temporary value that doesn't live outside of the scope。
我把修复引入恐慌报价,因为这不是真正正确的解决方案。正确的做法是使用函数指针:
lazy_static! {
static ref HASHES: HashMap<&'static str, fn(&[u8]) -> String> = {
let mut m = HashMap::new();
m.insert("md5", md5 as fn(&[u8]) -> std::string::String);
m
};
}
老实说,我说HashMap
可能有点过分;我使用的是阵列。小数组可能比小HashMap
:
type HashFn = fn(&[u8]) -> String;
static HASHES: &'static [(&'static str, HashFn)] = &[
("md5", md5),
];
你可以从遍历列表开始,或者可能是花哨的并按字母顺序排列它,然后当它变得更大时使用binary_search
。