動態

詳情 返回 返回

rust使用hashmap存儲函數並調用 - 動態 詳情

背景

rust 1.67.1 (d5a82bbd2 2023-02-07) 版本測試正常

使用rusthashmap存儲i32key, 函數作為value, 當查詢某個key如果存在具體的函數則調用

支持異步函數存儲與調用

主要方法

  • 如果類型不同,則需要包一層Box,把存儲的內容放到堆內存上,保證編譯器可以正常計算內存大小,主要是針對存儲在棧上的內存大小
  • 如果是異步方法,由於異步函數沒有聲明Unpin,所以需要包一層Pin,使用Box::pin實現,主要是保證異步函數運行的時候不會移動future

同步函數,相同參數,相同返回值的實現

use std::collections::HashMap;

fn first(value: i32) -> i32 {
    println!("{value} in sync first");
    value
}

fn second(value: i32) -> i32 {
    println!("{value} in sync second");
    value
}

type HashMapFun = HashMap<i32, Box<dyn Fn(i32) -> i32>>;

fn main() {
    let mut map: HashMapFun= HashMap::new();
    map.insert(1, Box::new(first));
    map.insert(2, Box::new(second));
    for v in 0..4 {
        map.get(&v).and_then(|f| Some(f(v)));
    }
}

同步函數-相同參數-不同返回值的實現

  • 由於返回的值不同,所以每個存儲的函數返回值都被包含了一層Box
  • hashmap插入函數的時候編譯器期望的是一個trait object,如果直接傳遞first或者second會發生報錯,可以只要閉包解決
use std::collections::HashMap;
use std::fmt::Display;

fn first(value: i32) -> Box<impl Display> {
    println!("{value} in sync first");
    Box::new(value)
}

fn second(value: i32) -> Box<String> {
    println!("{value} in sync second");
    Box::new(format!("-----{value}"))
}

type HashMapFun = HashMap<i32, Box<dyn Fn(i32) -> Box<dyn Display>>>;

fn main() {
    let mut map: HashMapFun = HashMap::new();
    map.insert(1, Box::new(|x| first(x)));
    map.insert(2, Box::new(|x| second(x)));
    for v in 0..4 {
        map.get(&v).and_then(|f| Some(f(v)));
    }
}

異步函數-相同參數-相同返回值的實現

use std::collections::HashMap;
use std::future::Future;
use std::pin::Pin;

async fn third(value: i32) -> i32 {
    println!("{value} in async third");
    tokio::time::sleep(std::time::Duration::from_secs(1)).await;
    value
}

async fn fourth(value: i32) -> i32 {
    println!("{value} in async fourth");
    tokio::time::sleep(std::time::Duration::from_secs(1)).await;
    value
}

type HashMapAsyncFun = HashMap<i32, Box<dyn Fn(i32) -> Pin<Box<dyn Future<Output = i32>>>>>;

#[tokio::main]
async fn main() {
    let mut async_map: HashMapAsyncFun  =
        HashMap::new();
    async_map.insert(3, Box::new(|x| Box::pin(third(x))));
    async_map.insert(4, Box::new(|x| Box::pin(fourth(x))));
    for v in 0..5 {
        if let Some(f) = async_map.get(&v) {
            f(v).await;
        }
    }
}

參考閲讀

Rust小技巧 - 把異步函數放進vector當中

Cannot use "impl Future" to store async function in a vector

user avatar niandb 頭像 jordan_haidee 頭像 xiaohe0601 頭像 decaday 頭像 rustfs 頭像 guishangguandao 頭像 shanliangdeshou_ccwzfd 頭像 more-sleep 頭像 liy 頭像 czy 頭像 lzfhope 頭像 hope_wisdom 頭像
點贊 14 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.