在Rust开发中,错误处理一直是一个重要且复杂的话题。今天要介绍的thiserror库,能让我们的错误处理代码变得优雅且强大。无论你是Rust新手还是老手,这篇文章都值得一读。 1. 什么是thiserror?thiserror是一个轻量级的错误处理库,通过过程宏的方式帮助我们轻松创建和管理自定义错误类型。它的设计理念是'简单直接',不引入额外的运行时开销。 2. thiserror的作用
3. 核心功能
4. 六个精选实例示例1:基础文件操作use thiserror::Error; use std::fs; use std::path::PathBuf;
#[derive(Error, Debug)] enum FileError { #[error('文件 {path} 读取失败')] ReadError { path: PathBuf, #[source] source: std::io::Error, }, #[error('文件不存在: {0}')] NotFound(PathBuf), }
fn read_file(path: PathBuf) -> Result<String, FileError> { if !path.exists() { return Err(FileError::NotFound(path)); } fs::read_to_string(&path).map_err(|e| FileError::ReadError { path, source: e, }) }
fn main() { let result = read_file(PathBuf::from('not_exists.txt')); println!('读取结果: {:?}', result); } 这个示例展示了:
示例2:参数验证
这个示例展示了:
示例3:HTTP请求错误use thiserror::Error; use reqwest; use std::time::Duration;
#[derive(Error, Debug)] enum ApiError { #[error('HTTP请求失败: {0}')] RequestFailed(String), #[error('请求超时')] Timeout, #[error(transparent)] ReqwestError(#[from] reqwest::Error), }
async fn fetch_data(url: &str) -> Result<String, ApiError> { let client = reqwest::Client::new(); let response = client .get(url) .timeout(Duration::from_secs(5)) .send() .await .map_err(|e| { if e.is_timeout() { ApiError::Timeout } else { ApiError::RequestFailed(e.to_string()) } })?; response.text().await.map_err(ApiError::from) }
#[tokio::main] async fn main() { let result = fetch_data('https://api.github.com').await; println!('请求结果: {:?}', result); } 这个示例展示了:
示例4:配置解析
这个示例展示了:
示例5:数据库操作use thiserror::Error; use sqlx::sqlite::SqlitePool;
#[derive(Error, Debug)] enum DbError { #[error('数据库连接失败: {0}')] ConnectionError(String), #[error('查询执行失败')] QueryError(#[from] sqlx::Error), #[error('记录不存在: ID = {0}')] NotFound(i64), }
async fn get_user(pool: &SqlitePool, id: i64) -> Result<String, DbError> { let result = sqlx::query!('SELECT name FROM users WHERE id = ?', id) .fetch_optional(pool) .await?; match result { Some(row) => Ok(row.name.expect('name column not found')), None => Err(DbError::NotFound(id)), } }
#[tokio::main] async fn main() -> Result<(), DbError> { let pool = SqlitePool::connect('sqlite::memory:') .await .map_err(|e| DbError::ConnectionError(e.to_string()))?; let user = get_user(&pool, 1).await; println!('查询结果: {:?}', user); Ok(()) } 这个示例展示了:
示例6:自定义错误链
这个示例展示了:
最佳实践建议
总结thiserror极大地简化了Rust中的错误处理流程,它:
通过以上示例,我们可以看到thiserror在各种场景下的应用。无论是简单的文件操作,还是复杂的业务逻辑,thiserror都能帮助我们写出更优雅的错误处理代码。 |
|
来自: 西北望msm66g9f > 《生产力》