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

粗犷型程序员

10 声望
3 粉丝
0 条评论
推荐阅读
linux获取存储设备信息
linux系统挂载了存储设备之后会有一些信息生成,这时候可以通过一些命令查看获取存储设备的信息有些命令和工具可能系统没有自带,需要执行安装操作,像Ubuntu系统一般执行apt install 工具名称就可以了/proc/part...

龚正阳阅读 232

4.8 Beijing Rust Meetup | Call For Presenters
如果你有兴趣参与探讨Rust作为一种强调性能、安全和并发性的编程语言的各种应用、实践和无限可能性的头脑风暴,就一定不能错过这场来自达坦科技、南京大学、CloudWeGo、华为等技术专家带来的关于Rust编程语言相关...

Datenlord阅读 1.4k

封面图
常用Linux系统命令、vim编辑命令汇总(看一遍用时候来查)
Linux操作基本操作pwd命令作用:显示当前工作目录用法:pwdcd命令作用:改变目录位置用法:cd [option] [dir]cd 目录路径 -进入指定目录cd .. -返回父目录cd / -进入根目录cd或cd ~ -进入用户主目录ls命令用法:l...

笑忘书阅读 1.1k

倒计时3天 I 4.8 Beijing Rust Meetup
对Rust编程语言感兴趣的你准备好相聚进行一场头脑风暴了吗?赶快预约报名参与本周六下午的线下Meetup。一起和来自达坦科技、南京大学、CloudWeGo、华为等的技术专家来探讨Rust作为一种强调性能、安全和并发性的编...

Datenlord阅读 1.1k

封面图
使用rust开发android底层
本文档使用rust开发android程序,只涉及到底层开发,不涉及任何ui相关,开发前推荐安装好magisk框架,方便后面获取手机root权限,或者有别的方案可以使adb获取到root权限也行

龚正阳阅读 1k

精彩回顾|4.8 Beijing Rust Meetup
2023年4月8日,达坦科技联合南京大学、CloudWeGo、华为等技术专家成功举办了题为Rust X的meetup。开发者们不仅线下积极报名参与,更在线上直播中踊跃参与互动,一起探讨Rust作为一种强调性能、安全和并发性的编程...

Datenlord阅读 979

封面图
关于rust交叉编译的问题
获取镜像的时候由于是直接拉ghcr.io/cross-rs/*的镜像,所以国内配置的镜像是无法使用的,这个时候需要配置docker的代理服务才行

龚正阳阅读 925

粗犷型程序员

10 声望
3 粉丝
宣传栏