44、thiserror
thiserror
前面讲的那几节专门为了thiserror
铺垫显得有点绕道,不是吗?但这是必要的!
让我们重回正轨:自定义错误类型和thiserror
。
自定义错误类型
之前已经学过了如何为自定义错误类型“手动”实现Error
trait。
试想一下,我们必须为代码库中的绝大多数错误类型做这件事情的话,会有很多的boilerplate
(样板)。
我们可以通过thiserror
删除一些样板,这是一个Rust的crate,它提供了一些procedural macro
(过程宏)来简化自定义错误类型的创建。
#[derive(thiserror::Error, Debug)]
enum TicketNewError {
#[error("{0}")]
TitleError(String),
#[error("{0}")]
DescriptionError(String),
}
我们可以编写我们自己的宏
到目前为止,我们看到的所有的derive macro
(派生宏)都是由Rust标准库提供的。
thiserror::Error
就是一个第三方derive macro
(派生宏)的例子。
derive macro
(派生宏)是procedural macro
(过程宏)的一个子集,是一种在编译时生成Rust代码的方式。我现在看的这个课程不会详细介绍如何编写过程宏,但是重要的是这个编写派生宏的方式还得去学。
这是一个在更高级的Rust课程中讨论的话题。
自定义语法
每个过程宏和都可以定义它自己的语法,通常在这个crate的文档里会有解释。对于thiserror
而言,我们有:
#[derive(thiserror::Error)]
:这是为自定义错误类型派生Error
trait的语法,由thiserror
提供帮助。#[error(“{0}”)]
这是为自定义错误类型的每个变体定义Display
实现的语法。当错误被display
(显示)时,{0}
将被变体的第0个字段所替换(在本例中是String)。
练习
这次的练习就是用thiserror
重写之前的TicketNewError
方法。
题目:
// TODO: Implement the `Error` trait for `TicketNewError` using `thiserror`.
// We've changed the enum variants to be more specific, thus removing the need for storing
// a `String` field into each variant.
// You'll also have to add `thiserror` as a dependency in the `Cargo.toml` file.
/* TODO */
pub enum TicketNewError {
/* TODO */
TitleCannotBeEmpty,
/* TODO */
TitleTooLong,
/* TODO */
DescriptionCannotBeEmpty,
/* TODO */
DescriptionTooLong,
}
#[derive(Debug, PartialEq, Clone)]
pub struct Ticket {
title: String,
description: String,
status: Status,
}
#[derive(Debug, PartialEq, Clone)]
pub enum Status {
ToDo,
InProgress { assigned_to: String },
Done,
}
impl Ticket {
pub fn new(
title: String,
description: String,
status: Status,
) -> Result<Ticket, TicketNewError> {
if title.is_empty() {
return Err(TicketNewError::TitleCannotBeEmpty);
}
if title.len() > 50 {
return Err(TicketNewError::TitleTooLong);
}
if description.is_empty() {
return Err(TicketNewError::DescriptionCannotBeEmpty);
}
if description.len() > 500 {
return Err(TicketNewError::DescriptionTooLong);
}
Ok(Ticket {
title,
description,
status,
})
}
}
要改动的地方也不多,就那一个枚举类型声明那一块。
首先在cargo.toml
文件里引入这个依赖:
然后按照这节学的内容开始编写代码:
#[derive(thiserror::Error, Debug)]
pub enum TicketNewError {
#[error("Title cannot be empty")]
TitleCannotBeEmpty,
#[error("Title cannot be longer than 50 bytes")]
TitleTooLong,
#[error("Description cannot be empty")]
DescriptionCannotBeEmpty,
#[error("Description cannot be longer than 500 bytes")]
DescriptionTooLong,
}
不过还是必须要加Debug
:
之后就可以了。
这几节的内容就是包管理和错误处理,对工程开发也是有很大的帮助。
这一节就先到这里了。
阅读剩余
版权声明:
作者:CN059
链接:https://www.cn059.com/2025/09/17/44%e3%80%81thiserror.html
文章版权归作者所有,未经允许请勿转载。
THE END