rust 用“or_insert_with”异步更新哈希Map

hrysbysz  于 2023-02-23  发布在  其他
关注(0)|答案(1)|浏览(152)

当Map还没有条目时,我试图用异步调用从DB中惰性地填充HashMap。
Rust编译器警告说异步闭包不稳定,但我应该尝试async {
我尝试遵循这个建议,但我在评论中得到了expected a FnOnce〈()〉closure错误:

use std::collections::HashMap;
use tokio::runtime::Runtime;

async fn get_from_store(key: String) -> String {
    // pretend to get this from an async sqlx db call
    String::from(format!("value-for-{key}"))
}

async fn do_work() {
    let mut map: HashMap<String, String> = HashMap::new();

    let key = String::from("key1");

    // the compiler advised async closures were unstable and...
    // to use an async block, remove the `||`: `async {` (rustc E0658)
    map.entry(key.clone())
        .or_insert_with(async { get_from_store(key) }.await);

    // the above now gives the error:
    //expected a `FnOnce<()>` closure, found `impl Future<Output = String>...xpected an `FnOnce<()>` closure, found `impl Future<Output = String>`

    for (key, value) in &map {
        println!("{}: {}", key, value);
    }
}

fn main() {
    let runtime = Runtime::new().unwrap_or_else(|e| panic!("Haha: {e}"));
    let result = do_work();
    match runtime.block_on(result) {
        _ => {}
    }
}

可能有理由不通过异步更新HashMap,但上面的错误给了我希望,我只是做错了...

eaf3rand

eaf3rand1#

你不能在那个位置使用.await,因为它要求闭包的返回类型是Future,但是or_insert_with的签名不要求这样。
我会做得更简单,将.await保留在您已经拥有的async函数中:

use std::collections::hash_map::Entry;

async fn do_work() {
    let mut map: HashMap<String, String> = HashMap::new();
    let key = String::from("key1");

    if let Entry::Vacant(entry) = map.entry(key.clone()) {
        entry.insert(get_from_store(key).await);
    }

    for (key, value) in &map {
        println!("{}: {}", key, value);
    }
}

相关问题