You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写以接收闭包为参数的闭包作为参数的Rust函数?

问题描述

我想编写一个函数,它接收一个闭包作为参数,而这个闭包又以另一个闭包作为参数。示例代码如下:

fn test<F: Fn(G), G: Fn()>(f: F) {
    let print = || {
        println!("hello");
    };
    f(print);
}

fn main() {
    test(|print| {
        print();
    })
}

但这段代码编译时会报如下错误:

error[E0308]: 类型不匹配
 --> src/main.rs:5:7
  |
1 | fn test<F: Fn(G), G: Fn()>(f: F) {
  |                   - 期望的是这个类型参数
2 |     let print = || {
  |                 -- 找到的闭包
...
5 |     f(print);
  |     - ^^^^^ 期望类型参数 `G`,找到闭包
  |     |
  |     此函数的参数不正确
  |
  = note: 期望类型参数 `G`
                    找到闭包 `{closure@src/main.rs:2:17: 2:19}`

错误原因

原代码的泛型约束逻辑搞反了:G是由调用者传入的闭包F决定的类型参数,但函数内部创建的print是一个具体的匿名闭包类型,无法匹配调用者指定的任意G类型,因此触发类型不匹配错误。

解决方案

我们需要调整泛型约束,让F能接受任意实现Fn()的闭包,而非绑定到某个特定的G类型,以下是几种可行写法:

方法1:使用impl Trait简化约束

这是最简洁的写法,直接声明F可以接受任意实现Fn()的类型作为参数:

fn test<F>(f: F)
where
    F: Fn(impl Fn()),
{
    let print = || {
        println!("hello");
    };
    f(print);
}

fn main() {
    test(|print| {
        print();
    });
}

方法2:明确泛型约束关系

如果需要更清晰的泛型声明,可以将G的约束绑定到F的参数要求上,同时指定内部闭包的类型:

fn test<F, G>(f: F)
where
    G: Fn(),
    F: Fn(G),
{
    let print: G = || {
        println!("hello");
    };
    f(print);
}

fn main() {
    test(|print| {
        print();
    });
}

这种写法下,G由调用者的闭包推导而来,内部的print闭包必须与该类型一致。

方法3:使用 trait 对象(动态分发)

如果需要更大的灵活性,允许f接受不同类型的闭包,可以使用Box<dyn Fn()> trait 对象,代价是轻微的运行时开销:

fn test<F>(f: F)
where
    F: Fn(Box<dyn Fn()>),
{
    let print = Box::new(|| {
        println!("hello");
    });
    f(print);
}

fn main() {
    test(|print| {
        print();
    });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 00:10:15