Rust的错误处理
概述Rust 偷师 Haskell构建了对标Maybe的Option 类型和对标Either 的Result 类型Option 和 ResultOption 是一个 enum其定义如下pubenumOptionT{None,Some(T)}它可以承载有值 / 无值这种最简单的错误类型Result 是一个更加复杂的 enum, 其定义如下:#[must_use this Result may be an Err variant, which should be handle]pubenumResultT,E{Ok(T),Err(E)}当函数出错时可以返回Err(E), 否则 Ok(T)Result 类型声明时还有个must_use 的标注编译器会对有 must_use 标注的所有类型做特殊处理如果该类型对应的值没有被显式使用则会告警。这样保证错误被妥善处理操作符所以在Rust 代码中如果你只想传播错误不想就地处理可以用 操作符usestd::fs::File;usestd::io::Read;fnread_file(name:str)-ResultString,std::io::Error{letmutfFile::open(name)?;letmutcontentsString::new();f.read_to_string(mutcontents);Ok(contents);}通过 操作符Rust 让错误传播的代价和异常处理不相上下同时又避免了异常处理的诸多问题? 操作符内部被展开成类似这样的代码matchresult{Ok(v)v,Err(e)returnErr(e.into())}所有我们可以方便写出类似这样的代码简洁易懂可读性很强fut.await?.process()?.next().await?;整个代码的执行流程如下:虽然 操作符使用起来非常方便但要注意在不同的错误类型之间是无法直接使用的需要实现From trait 在二者之间建立起转换的桥梁这会带来额外的麻烦函数式错误处理Rust 还为Option 和 Result 提供了大量的辅助函数如 map / map_err / add_then 你可以很方便地处理数据结构中部分情况通过这些函数可以很方便地对错误处理引入 Railroad oriented programming 范式。比如用户注册的流程你需要校验用户输入对数据进行处理转换然后存入数据中Ok(data).add_then(validate).add_then(process).map(transform).and_then(store).map_error(...)执行流程如下图所示:此外Option 和 Result 的互相转换也很方便这也得益于Rust 构建的强大的函数式编程能力panic! 和 catch_unwind使用 Option 和 Result 是 Rust 中处理错误的首选绝大多数时候我们也应该使用但Rust 也提供了特殊的异常处理能力在 Rust 看来一旦你需要抛出异常那抛出的一定是严重的错误。所以Rust 跟 Golang 一样使用了诸如panic! 这样的字眼警示开发者想清楚了再使用我在使用Option 和 Result 类型时开发者也可以对其unwarp() 或者 expect() 强制把Option 和 ReulstT, E 转换成 T如果无法完成这种转换也会panic! 出来一般而言panic! 是 不可恢复或者不想恢复错误。希望在此刻程序终止运行并得到崩溃信息比如下面的代码它解析 noise protoco 的协议变量letparams:NoiseParamsNoise_XX_25519_AESGCM_SHA256.parse().unwrap();如果开发者小小心把协议变量写错了最佳的方式是立刻panic! 出来让错误立刻暴露以便解决这个问题有些场景下也希望能够像异常处理那样能够栈回溯把环境恢复到捕获异常的上下文。Rust 标准库下提供了catch_unwind(), 把调用栈回溯到 catch_unwind 这一刻作用和其他语言的 try {…} catch {…}usestd::painic;fnmain(){letresultpanic::catch_unwind(||{println(hello!);});assert!(result.is_ok());letresultpanic::catch_unwind(||{panic!(oh no!);});assert!(result.is_err());println!(panic captured: {:#?},result);}当然和异常处理一样并不意味你可以溢出这一特性我想这也是Rust 把 抛出异常称作 panic!, 而捕获异常称作 catch_unwind 的原因让初学者望而生畏不敢轻易使用catch_unwind 在某些场景下非常有用比如你在使用 Rust 为 erlang VM 撰写 NIF你不希望Rust 代码中的任何 panic! 导致 erlang VM 崩溃。因为崩溃是一个非常不好的体验它违背了 erlang 的 设计原则: process 可以 let it crash 但错误代码不该导致 VM 崩溃你就可以把Rust 代码整个封装在 catch_unwind() 函数所需要传入的闭包中这样一旦任何代码中包括第三方crates 的代码含有能够导致 panic! 的代码都会被捕获并被转换为一个ResultError trait 错误类型的转换为了规范这个代表错误的数据类型行为Rust 定义了 Error traitpubtraitError:DebugDisplay{fnsource(self)-Option(dynErrorstatic){...}fnbacktrace(self)-OptionBacktrace{...}fndescription(self)-str{...}fncause(self)-OptiondynError{...}}定义自己的数据类型然后为其实现 Error trait不过这样的工作已经有人替人简化了可以使用 thiserror 和 anyhow 来简化这个步骤。thiserror 提供了一个派生宏(drive macro) 来简化错误类型的定义usethiserror::Error;#[dervie(Error, Debug)]#[non_exhaustive]pubenumDataStoreError{#[error(data store disconnected)]Disconnect(#[from]io::Error),#[error(the data for key {0} is not available)]Redaction(String)#[error(invalid header (expected {expected:?}, found {found:?}))]InvalidHeader{expected:String,found:String},#[error(unknown data store error)]Unknown,}如果你在撰写一个Rust 库那么thiserror 可以很好地协助你对这个库里所有可能发生的错误进行建模而anyhow 实现了 anyhow::Error 和 任意符号 Error trait 的错误类型之间的转换让你可以使用操作符不必再手工转换错误类型anyhow 还可以让你容易抛出一些临时的错误而不必费力定义错误类型当然不提倡滥用这个能力建议开发前先用类似 thiserror 的库定义好你项目中主要的错误类型并随着项目的深入不断增加新的错误类型让系统中所有的潜在错误无所遁形

相关新闻

RUST 静态生命周期和动态生命周期

RUST 静态生命周期和动态生命周期

图例分配在堆和栈上的内存有其各自的作用域,它们的生命周期是动态的 全局变量、静态变量、字符串字母量、代码等内容,在编译时,会被编译到可执行文件中的 BSS/Data/RoData/Text 段,然后在加载时,装入内存 因而&#xf…

2026/7/27 19:00:42阅读更多 →
计算机毕业设计之基于SpringBoot的高校运动会管理系统的设计与实现

计算机毕业设计之基于SpringBoot的高校运动会管理系统的设计与实现

本研究致力于构建一种基于springboot的高校运动会管理系统,在开发本系统之前。本人通过学校老师、同学、图书馆的大量走访,通过了解相关的开发语言,以及对介绍了系统的分析与设计过程中,且仔细的概括了系统在开发后进行多次运行与…

2026/7/27 18:58:42阅读更多 →
计算机毕业设计之基于Springboot的高校智慧课堂系统的设计与实现

计算机毕业设计之基于Springboot的高校智慧课堂系统的设计与实现

在信息技术飞速发展的时代背景下,高校教学模式正经历着深刻的变革,智慧课堂系统应运而生。本论文聚焦于高校选课系统的设计与实现,旨在借助先进的技术手段提升教学质量与效率,推动教育教学的信息化进程。本系统采用Java语言进行开…

2026/7/27 18:58:42阅读更多 →
.NET CORE 认证模块-注册方案与请求认证探究

.NET CORE 认证模块-注册方案与请求认证探究

.NET CORE 认证模块-注册方案与请求认证探究 一、认证模块的基础认知在 .NET Core 中,认证模块是一个核心的安全组件,它负责验证用户的身份。认证过程包括两个关键阶段:注册方案和请求认证。注册方案定义了认证的方式(如 Cookie、…

2026/7/27 20:18:49阅读更多 →
Windows 7系统核心功能与优化全解析

Windows 7系统核心功能与优化全解析

1. Windows 7操作系统概述Windows 7作为微软公司2009年发布的经典操作系统,至今仍在许多企业和个人电脑中广泛使用。相比前代Vista系统,它在性能优化、用户界面和稳定性方面都有显著提升。我使用Win7系统长达8年时间,从日常办公到专业软件运行…

2026/7/27 20:18:49阅读更多 →
Allure 1常见问题解决:15个你必须知道的技巧

Allure 1常见问题解决:15个你必须知道的技巧

Allure 1常见问题解决:15个你必须知道的技巧 【免费下载链接】allure1 Allure 1 isnt supported any more, please consider using Allure 2 https://github.com/allure-framework/allure2 instead 项目地址: https://gitcode.com/gh_mirrors/al/allure1 All…

2026/7/27 20:18:49阅读更多 →
GANSketching高级技巧:掌握 latent space 插值,创造流畅过渡的AI绘画效果

GANSketching高级技巧:掌握 latent space 插值,创造流畅过渡的AI绘画效果

GANSketching高级技巧:掌握 latent space 插值,创造流畅过渡的AI绘画效果 【免费下载链接】GANSketching Sketch Your Own GAN: Customizing a GAN model with hand-drawn sketches. 项目地址: https://gitcode.com/gh_mirrors/ga/GANSketching G…

2026/7/27 20:18:49阅读更多 →
C++视频字幕解析实战:FFmpeg+Tesseract实现硬字幕提取

C++视频字幕解析实战:FFmpeg+Tesseract实现硬字幕提取

1. 项目概述:从需求到实现的思考路径最近在做一个需要批量处理视频、提取其中字幕信息的项目,发现市面上的工具要么功能臃肿,要么无法满足自定义的解析逻辑。作为一个习惯了自己动手的C开发者,我决定写一个轻量、高效、可嵌入的C视…

2026/7/27 20:18:49阅读更多 →
深入解析DP83816以太网控制器:从MAC/PHY集成到寄存器配置实战

深入解析DP83816以太网控制器:从MAC/PHY集成到寄存器配置实战

1. 项目概述如果你在嵌入式系统、工业控制或者老式PC主板维修的领域里摸爬滚打过,那么对德州仪器(TI)的DP83816这颗芯片一定不会陌生。它是一款经典的、高度集成的10/100 Mb/s以太网控制器,江湖人称“MacPhyter-II”。这个名字就点…

2026/7/27 20:16:49阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/27 1:14:34阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/27 1:14:52阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/27 1:14:56阅读更多 →
SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

1. 项目概述:从寄存器手册到实战指南 如果你手头有一份类似德州仪器(TI)TMS320x240xA系列DSP的SPI模块技术手册,看着里面密密麻麻的寄存器位定义、时序图和公式,是不是感觉头大?这份资料虽然权威&#xff0…

2026/7/27 0:00:24阅读更多 →
【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/27 0:00:24阅读更多 →
2007-2023年各市区县生态文明建设示范区DID

2007-2023年各市区县生态文明建设示范区DID

数据简介 自改革开放以来,我国依赖高投入、高资源消耗和高污染等传统发展模式实现了经济短期内的快速增长, 然而这也导致了严重的生态环境危机。因此,国家有力于推动企业高质量经济发展,协同生态保护的方针,从而从201…

2026/7/27 0:00:24阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/27 16:57:54阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/26 19:05:21阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/26 19:05:21阅读更多 →