【Rust自学】19.3. 高级函数和闭包 19.3 高级函数和闭包19.3.1 函数指针我们已经讲过把闭包传进函数。实际上我们也可以把函数传进函数。在传递时函数会被强制转换成fn类型这就是函数指针。例如fn add_one(x: i32) - i32 { x 1 } fn do_twice(f: fn(i32) - i32, arg: i32) - i32 { f(arg) f(arg) } fn main() { let answer do_twice(add_one, 5); println!(The answer is: {answer}); }do_twice的第一个参数f的类型是fn也就是函数指针。它期望一个参数类型为i32、返回类型也为i32的函数。函数体中调用了两次f。输出The answer is: 12函数指针与闭包的区别闭包至少实现了Fn、FnOnce和FnMut这三个 trait 之一。函数指针fn是一个类型不是 trait。我们可以直接把fn指定为参数类型而不必声明一个以Fntrait 为约束的泛型参数。函数指针实现了全部三种闭包 trait也就是Fn、FnOnce和FnMut。所以你总是可以把函数指针作为参数传给接受闭包的函数。正因为如此我们编写函数时通常更倾向于使用带闭包 trait 的泛型参数因为这样函数既能接受闭包也能接受普通函数。在某些情况下我们可能想接受fn类型而不是闭包例如与不支持闭包的代码交互时比如 C 函数。该怎么写呢看一个例子fn main() { let list_of_numbers vec![1, 2, 3]; let list_of_strings: VecString list_of_numbers .iter() .map(|i| i.to_string()) .collect(); // 分行只是为了可读性并不是必须的 }list_of_numbers中的元素是i32我们想把它们转换成String赋给list_of_strings。步骤是- 先用iter产生一个迭代器- 再用map中的闭包|i| i.to_string()转换每个元素- 最后用collect把所有转换后的元素收集成一个集合这段代码也可以这样写fn main() { let list_of_numbers vec![1, 2, 3]; let list_of_strings: VecString list_of_numbers .iter() .map(ToString::to_string) .collect(); }区别在于.map(ToString::to_string)这里直接传入了to_string函数。效果与上一版相同。顺便一提ToString::to_string使用了 19.2. 高级 trait关联类型、默认泛型参数和运算符重载、完全限定语法、supertrait 和 newtype 讨论过的完全限定语法。来看一下map的定义fn mapB, F(self, f: F) - MapSelf, F where Self: Sized, F: FnMut(Self::Item) - Bmap要求f实现FnMuttrait而闭包和函数指针都满足这个要求所以两者都可以传入。再看另一个例子fn main() { enum Status { Value(u32), Stop, } let list_of_statuses: VecStatus (0u32..20) .map(Status::Value) .collect(); }注意map的参数。我们使用构造函数Status::Value对范围内的每个u32调用map并创建Status::Value实例。有人可能会问Status::Value不是枚举变体吗怎么变成函数了这是因为在 Rust 中这样的构造函数被实现为接收一个参数并返回新实例的函数。换句话说let v Status::Value(3);这只是一个例子。这里初始化了v而Status::Value(3)可以看作一次构造函数调用3是构造函数的参数。由于构造函数被实现为函数我们可以把它们当作函数来用3就是它们的参数。所以我们也可以把这类构造函数用作实现了闭包 trait 的函数指针。19.3.2 返回闭包闭包通过 trait 来表达因此不能直接从函数返回闭包。相反你可以返回一个实现了该 trait 的具体类型。例如fn returns_closure() - dyn Fn(i32) - i32 { |x| x 1 }这个函数试图直接返回一个闭包。输出error[E0746]: return type cannot be a trait object without pointer indirection -- src/lib.rs:1:25 | 1 | fn returns_closure() - dyn Fn(i32) - i32 { | ^^^^^^^^^^^^^^^^^^ doesnt have a size known at compile-time | help: consider returning an impl Trait instead of a dyn Trait | 1 - fn returns_closure() - dyn Fn(i32) - i32 { 1 fn returns_closure() - impl Fn(i32) - i32 { | help: alternatively, box the return type, and wrap all of the returned values in Box::new | 1 ~ fn returns_closure() - Boxdyn Fn(i32) - i32 { 2 ~ Box::new(|x| x 1) | For more information about this error, try rustc --explain E0746. error: could not compile functions-example (lib) due to 1 previous errorRust 不知道需要多少空间来存储这个闭包所以会报错。还记得我们以前在哪里遇到过同样的“Rust 不知道该分配多少空间”的错误吗没错——在学习链表时。当时的解决办法是用BoxT包裹链表这里也可以这样做fn returns_closure() - Boxdyn Fn(i32) - i32 { Box::new(|x| x 1) }因为返回值位于指针之后返回类型现在在编译时就有了已知大小。

相关新闻

最新新闻

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现 【免费下载链接】serenity The Serenity Operating System 🐞 项目地址: https://gitcode.com/GitHub_Trending/se/serenity 导读 本文以 getopt(3) 手册 为核心&a…

2026/10/1 19:32:24
轻量服务器还是ECS?大促云服务器选购与避坑实战指南

轻量服务器还是ECS?大促云服务器选购与避坑实战指南

每年大促节点,群里永远有人在问同一个问题:“38元的轻量服务器到底怎么抢?为什么我每次点进去都是已售罄?68元直购和99元的ECS我到底选哪个?”作为一个常年帮团队和自己采购云服务器的老用户,我太清楚这种纠…

2026/9/30 21:32:07
为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南

为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南

为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南 【免费下载链接】agents Multi-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity 项目地址:…

2026/9/30 19:41:56
PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署

PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署

PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署 【免费下载链接】PaddleOCR Turn any PDF or image document into structured data for your AI. A powerful, lightweight OCR toolkit that bridges the gap between i…

2026/10/1 19:32:23
Spring源码解析:构造器注入的类型转换与候选匹配机制

Spring源码解析:构造器注入的类型转换与候选匹配机制

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 19:32:35
openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由

openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由

openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由 【免费下载链接】openai-agents-python A lightweight, powerful framework for multi-agent workflows 项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-pyth…

2026/9/30 21:32:11

日新闻

周新闻

月新闻