Rust:专业级错误处理工具 thiserror 详解

Rust:专业级错误处理工具 thiserror 详解

thiserror 是 Rust 中用于高效定义自定义错误类型的库,特别适合库开发。相比 anyhow 的应用级错误处理,thiserror 提供更精确的错误控制,让库用户能模式匹配具体错误。


📦 基本安装

Cargo.toml 中添加:

[dependencies]
thiserror = "1.0"

🧩 核心功能

1. 基础错误定义

use thiserror::Error;#[derive(Error, Debug)]
enum MyError {#[error("File not found: {0}")]NotFound(String),#[error("I/O error occurred")]Io(#[from] std::io::Error),#[error("Validation failed for {field}: {reason}")]Validation {field: &'static str,reason: String,},
}

2. 自动实现特征

自动为你的类型实现:

  • std::error::Error
  • Display(通过 #[error] 属性)
  • From(通过 #[from] 属性)

🛠️ 属性详解

1. #[error("格式化字符串")]

定义错误的显示信息:

#[error("Invalid value: {value} (allowed: {allowed_values:?})")]
InvalidValue {value: i32,allowed_values: Vec<i32>,
}

调用:

println!("{}", MyError::InvalidValue {value: 42,allowed_values: vec![1, 2, 3]
});
// 输出: Invalid value: 42 (allowed: [1, 2, 3])

2. #[source]

标记错误来源(自动实现 Error::source):

#[derive(Error, Debug)]
#[error("Config load failed")]
struct ConfigError {#[source]   // 标记错误来源字段source: std::io::Error,
}

3. #[from]

自动实现 From 转换:

#[derive(Error, Debug)]
enum ParseError {#[error("Integer parsing failed")]Int(#[from] std::num::ParseIntError),#[error("Float parsing failed")]Float(#[from] std::num::ParseFloatError),
}// 自动转换
fn parse(s: &str) -> Result<f64, ParseError> {let parts: Vec<&str> = s.split(':').collect();let x: i32 = parts[0].parse()?;  // 自动转为 ParseError::Intlet y: f64 = parts[1].parse()?;  // 自动转为 ParseError::FloatOk((x as f64) * y)
}

4. #[backtrace]

自动捕获回溯信息:

#[derive(Error, Debug)]
#[error("Connection failed")]
struct ConnectionError {#[backtrace]   // 自动记录回溯source: std::io::Error,
}

📚 结构体错误定义

#[derive(Error, Debug)]
#[error("Database error (code {code}): {message}")]
struct DbError {code: u32,message: String,#[source]inner: diesel::result::Error, // 底层错误
}

🔀 错误转换

#[derive(Error, Debug)]
enum AppError {#[error("HTTP error: {0}")]Http(#[from] HttpError),#[error("Database error")]Db(#[from] DbError),
}fn handle_request() -> Result<(), AppError> {let data = fetch_data()?;       // HttpError -> AppError::Httpsave_to_db(&data)?;             // DbError -> AppError::DbOk(())
}

⚡ 实用技巧

1. 添加额外上下文

fn read_config() -> Result<Config, MyError> {let path = "config.toml";let content = std::fs::read_to_string(path).map_err(|e| MyError::Io(e).context(format!("Failed to read {}", path)))?;// ...
}

2. 条件性字段

#[derive(Error, Debug)]
#[error("Operation failed{}{}", .details.as_ref().map(|s| format!(": {}", s)).unwrap_or_default())]
struct OpError {details: Option<String>,#[source]source: anyhow::Error,
}

3. 组合使用宏

fn parse_number(s: &str) -> Result<i32, ParseError> {s.parse().map_err(|e| {// 添加上下文信息ParseError::InvalidFormat {input: s.to_string(),#[source] e}})
}

💡 最佳实践

  1. 库开发优先:在编写供他人使用的库时使用 thiserror
  2. 精准错误类型:使用枚举覆盖所有可能错误
  3. 丰富错误信息:通过格式化字符串暴露有用信息
  4. 区分层级
    #[derive(Error, Debug)]
    enum ApiError {#[error(transparent)]Request(#[from] RequestError),#[error(transparent)]Parsing(#[from] ParseError),#[error("Authentication failed")]Auth,
    }
    

⚠️ 常见错误解决

问题#[derive(Error)] 后未实现 Display
解决:确保每个变体都有 #[error] 属性

问题source 字段不工作
解决

  1. 添加 #[source]#[from] 属性
  2. 确保字段类型实现了 std::error::Error

🆚 thiserror vs anyhow

特性thiserroranyhow
适用场景库开发应用开发
错误类型强类型自定义错误通用错误类型 (anyhow::Error)
模式匹配支持精确匹配只支持粗略匹配
上下文添加需手动实现内置 .context()
性能更高效(无堆分配)错误路径有堆分配

当需要同时使用:

[dependencies]
anyhow = "1.0"
thiserror = "1.0"

完整文档参考:thiserror on crates.io

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/92965.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/92965.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python网络爬虫(一) - 爬取静态网页

文章目录一、静态网页概述1. 静态网页介绍2. 静态网页爬取技术Requests介绍二、安装 Requests 库三、发送请求并获取响应1. 发送 GET 请求1.1 get() 方法介绍1.2 get() 方法签名介绍1.3 get() 方法参数介绍1.4 示例&#xff1a;发送get请求2. 发送 POST 请求2.1 post() 方法介绍…

.NET/C# webapi框架下给swagger的api文档中显示注释(可下载源码)

bg&#xff1a;.NET/C#真的是越来越凉了。用的是.net9&#xff0c;创建完自带一个天气预报api拿来测试就行 1、在Controllers中弄多几个&#xff0c;并写上注释 /// <summary> /// Post注释 /// </summary> /// <returns></returns> [HttpPost] publ…

2508C++,检测S模式

原文 可用Windows.System.Profile.WindowsIntegrityPolicy类检测S模式. //C# using Windows.System.Profile; if (WindowsIntegrityPolicy.IsEnabled) {//系统在S模式if (WindowsIntegrityPolicy.CanDisable) {//系统在S模式,但可退出S模式suggestCompanion true;} else {//系…

Coding Exercising Day 9 of “Code Ideas Record“:StackQueue part 01

文章目录1. Theoretical basisThe C standard library has multiple versions. To understand the implementation principles of stack and queue, we must know which STL version we are using.The stack and queue discussed next are data structures in *SGI STL*. Only …

Mysql数据仓库备份脚本

Mysql数据仓库备份脚本 #!/bin/bash# MySQL数据库完整备份脚本 # 功能: 查询所有数据库 -> 分别导出 -> 压缩打包# 配置区域 # MySQL连接信息 MYSQL_USER"root" MYSQL_PASSWORD"root" MYSQL_HOST"localhost" MYSQL_PORT"3306"…

基于嵌入式Linux RK3568 qt 车机系统开发

嵌入式系统、Qt/QML 与车机系统的发展趋势分析 1. RK3568 开发板与 OpenGL ES 3 支持&#xff0c;为图形应用打下坚实基础 RK3568 是瑞芯微&#xff08;Rockchip&#xff09;推出的一款高性能、低功耗的64位处理器&#xff0c;广泛用于工业控制、智能终端、嵌入式车载系统等领…

OceanBase架构设计

本文主要参考《大规模分布式存储系统》 基本结构客户端&#xff1a;发起请求。 RootServer&#xff1a;管理集群中的所有服务器&#xff0c;子表数据分布及副本管理&#xff0c;一般为一主一备&#xff0c;数据强同步。 UpdateServer&#xff1a;存储增量变更数据&#xff0c;一…

[Element-plus]动态设置组件的语言

nuxt element-plus国际化vue element-plus国际化<template><div class"container"> <!-- <LangSwitcher />--><button click"toggle(zh-cn)">中文</button><button click"toggle(en)">English<…

【VS Code - Qt】如何基于Docker Linux配置Windows10下的VS Code,开发调试ARM 版的Qt应用程序?

如何在Windows 10上配置VS Code以开发和调试ARM版Qt应用程序。这需要设置一个基于Docker的Linux环境。首先&#xff0c;让我们了解一下你的具体需求和环境&#xff1a;你有一个Qt项目&#xff08;看起来是医学设备相关的设置程序&#xff09;目标平台是ARM架构你希望在Windows …

linux常见故障系列文章 1-linux进程挂掉原因总结和排查思路

问题一 &#xff1a;运行时常见的进程崩溃原因 内存不足&#xff09; **0. 内存不足 内存不足&#xff08;OOM Killer&#xff09; 排查 OOM&#xff1a;free -h → dmesg → ps aux --sort-%mem 预防 OOM&#xff1a;限制关键进程内存、调整 OOM Killer 策略、增加 swap 长期优…

Spring Cloud Gateway 路由与过滤器实战:转发请求并添加自定义请求头(最新版本)

前言 网关是什么?如果把你的系统比作一栋高端写字楼,网关就是那位神通广大的前台小姐姐,笑容可掬地拦住不速之客,把贵宾引到豪华会议室,还会在你胸口贴上一枚醒目的“贵宾”标签。它既懂礼数,又有原则,能过滤无效请求、转发正确目标,还能在途中动点“小手脚”,比如加…

达梦数据库慢SQL日志收集和分析

达梦数据库慢SQL日志收集和分析 开启SQL日志记录 使用DMLOG工具分析SQLLOG DMLOG安装配置 DMLOG分析日志 系统视图V$LONG_EXEC_SQLS记录了最近1000条执行时间超1s的sql。如果sql语句超长可能会被截断,只能从sqllog里找完整的sql文本。 SELECT * FROM V$LONG_EXEC_SQLS ORDER …

一篇文章,带你玩转SparkCore

Spark Core 概念 前言 批处理&#xff08;有界数据&#xff09; ​ 对静态的、有限的数据集进行一次性处理&#xff0c;数据通常按固定周期&#xff08;如每小时、每天&#xff09;收集后统一计算。 特点&#xff1a; 高吞吐量&#xff0c;适合大规模数据。高延迟&#xff08;数…

VRRP技术

VRRP的概念及应用场景 VRRP&#xff08;虚拟路由冗余协议&#xff09;概念 VRRP&#xff08;Virtual Router Redundancy Protocol&#xff0c;虚拟路由冗余协议&#xff09;是一种路由容错协议&#xff0c;用于在多个路由器之间提供网关冗余&#xff0c;确保当主路由器故障时&a…

表驱动法-灵活编程范式

表驱动法&#xff1a;从理论到实践的灵活编程范式 一、为什么需要表驱动法&#xff1f; 在处理多分支逻辑&#xff08;如消息解析、命令分发&#xff09;时&#xff0c;传统的 if-else 或 switch-case 存在明显局限&#xff1a; 当分支数量庞大&#xff08;如成百上千条命令&am…

零基础-动手学深度学习-10.2. 注意力汇聚:Nadaraya-Watson 核回归

上节介绍了框架下的注意力机制的主要成分 图10.1.3&#xff1a; 查询&#xff08;自主提示&#xff09;和键&#xff08;非自主提示&#xff09;之间的交互形成了注意力汇聚&#xff1b; 注意力汇聚有选择地聚合了值&#xff08;感官输入&#xff09;以生成最终的输出。 本节将…

nginx高新能web服务器

一、Nginx 概述和安装 Nginx是免费的、开源的、高性能的HTTP和反向代理服务器、邮件代理服务器、以及TCP/UDP代理服务器。 Nginx 功能介绍 静态的web资源服务器html&#xff0c;图片&#xff0c;js&#xff0c;css&#xff0c;txt等静态资源 http/https协议的反向代理 结合F…

Unity大型场景性能优化全攻略:PC与安卓端深度实践 - 场景管理、渲染优化、资源调度 C#

本文将深入探讨Unity在大型场景中的性能优化策略&#xff0c;涵盖场景管理、渲染优化、资源调度等核心内容&#xff0c;并提供针对PC和安卓平台的优化方案及实战案例。 提示&#xff1a;内容纯个人编写&#xff0c;欢迎评论点赞。 文章目录1. 大型场景性能挑战1.1 性能瓶颈定位…

Java集合框架、Collection体系的单列集合

Java集合框架、Collection1. 认识Java集合框架及结构1.1 集合框架整体结构1.2 集合框架的核心作用2. Collection的两大常用集合体系及各个系列集合的特点2.1 List系列集合&#xff08;有序、可重复&#xff09;2.2 Set系列集合&#xff08;无序、不可重复&#xff09;3. Collec…

HTML <picture> 元素:让图片根据设备 “智能切换” 的响应式方案

在响应式设计中&#xff0c;图片适配是一个绕不开的难题&#xff1a;同一张高清图片在大屏设备上清晰美观&#xff0c;但在小屏手机上可能加载缓慢&#xff1b;而适合手机的小图在桌面端又会模糊失真。传统的解决方案往往需要用JavaScript判断设备尺寸并动态替换图片源&#xf…