You need to enable JavaScript to run this app. Rust如何打印作为参数传入的Fn trait类型函数的名称
优惠活动
大模型
产品
解决方案
定价
更多

Rust如何打印作为参数传入的Fn trait类型函数的名称

解决方案

方案1:使用内置的类型名获取工具(无额外侵入性)

Rust 1.68及以上版本提供了std::any::type_name_of_val方法,可以直接获取任意值的类型名字符串。对于普通函数参数,该方法返回的结果就是函数的完整路径名,完全满足打印调试的需求。
修改你的代码如下:

use std::any::type_name_of_val;
use std::fmt::Debug;

pub async fn loop_until_hit_rate_limit<'a, T, Fut>(
    object_arr: &'a [T],
    settings: &'a Settings,
    pool: &'a PgPool,
    f: impl Fn(&'a Settings, &'a PgPool, &'a T) -> Fut + Copy,
    rate_limit: usize,
) where
    Fut: Future<Output = anyhow::Result<()>>,
    // 额外加Debug约束,保证前三个参数可以正常打印
    T: Debug,
    Settings: Debug,
    PgPool: Debug,
{
    // 执行业务逻辑
    println!("args were: {:?}, {:?}, {:?}, {}, {}", object_arr, settings, pool, type_name_of_val(&f), rate_limit);
}

限制说明

  • 如果传入的是捕获了变量的闭包,返回的类型名会包含编译器生成的闭包标识后缀,不会显示自定义名称,但仍可用于区分不同的闭包实例。
  • 泛型函数的返回结果会携带泛型参数的类型信息。

如果你使用的Rust版本低于1.68,无法使用type_name_of_val,可以把函数参数的闭包trait改为具体泛型参数,再用std::any::type_name获取:

pub async fn loop_until_hit_rate_limit<'a, T, Fut, F>(
    object_arr: &'a [T],
    settings: &'a Settings,
    pool: &'a PgPool,
    f: F,
    rate_limit: usize,
) where
    F: Fn(&'a Settings, &'a PgPool, &'a T) -> Fut + Copy,
    Fut: Future<Output = anyhow::Result<()>>,
    T: Debug,
    Settings: Debug,
    PgPool: Debug,
{
    println!("f name: {}", std::any::type_name::<F>());
}

方案2:手动绑定函数名(最精准可控)

如果你需要完全可控的函数名输出,不需要依赖编译生成的类型名,可以修改函数签名,新增一个函数名字段,调用时用stringify!宏直接传入传入函数的标识符:
修改后的函数签名:

pub async fn loop_until_hit_rate_limit<'a, T, Fut>(
    object_arr: &'a [T],
    settings: &'a Settings,
    pool: &'a PgPool,
    f: impl Fn(&'a Settings, &'a PgPool, &'a T) -> Fut + Copy,
    // 新增函数名参数
    f_name: &'static str,
    rate_limit: usize,
) where
    Fut: Future<Output = anyhow::Result<()>>,
    T: Debug,
    Settings: Debug,
    PgPool: Debug,
{
    // 执行业务逻辑
    println!("args were: {:?}, {:?}, {:?}, {}, {}", object_arr, settings, pool, f_name, rate_limit);
}

调用示例:

// 假设你要传入的函数名为my_handler
loop_until_hit_rate_limit(
    &obj_arr,
    &settings,
    &pool,
    my_handler,
    // 用stringify宏直接转标识符为字符串,不需要手动硬编码
    stringify!(my_handler),
    100
).await;

该方案的优势是完全精准,不管是普通函数还是自定义闭包,都可以传入你想要显示的名称,不会受编译器生成规则影响。

内容的提问来源于stack exchange,提问作者ilmoi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 11:06:03