39、Unwarp(拆封)
Unwarpping
这个Unwarp
,是Rust里面很重要的一个特性,中文可以翻译为拆封,不过我没见过有人用它的中文汉化的,还是保留英文名Unwarp
。
回到正题上来,上一节的习题为Ticket::new
实现了可处理异常的Result
返回值,Ticket::new
现在返回一个Result
,而不是直接对无效的输入数据panic。
这对函数调用者来说意味着什么呢?
错误(Failures)不能被隐式地忽略
与异常(exceptions)不同,Rust的Result
强制我们在调用点处理错误。
如果我们调用一个返回Result
的函数,Rust不允许我们隐式地忽略错误情况。
fn parse_int(s: &str) -> Result<i32, ParseIntError> {
// ...
}
// This won't compile: we're not handling the error case.
// We must either use `match` or one of the combinators provided by
// `Result` to "unwrap" the success value or handle the error.
let number = parse_int("42") + 2;
有了Result
,然后呢?
调用返回Result
的函数时,有两个关键选项:
- 如果操作失败,则panic。这是使用
unwarp
或expect
方法实现的。
// Panics if `parse_int` returns an `Err`.
let number = parse_int("42").unwrap();
// `expect` lets you specify a custom panic message.
// "expect" 为panic提供了自定义的错误信息
let number = parse_int("42").expect("Failed to parse integer");
- 使用
match
表达式对Result
进行解构,显式地处理异常情况。
match parse_int("42") {
Ok(number) => println!("Parsed number: {}", number),
Err(err) => eprintln!("Error: {}", err),
}
练习
题目:
// TODO: `easy_ticket` should panic when the title is invalid.
// When the description is invalid, instead, it should use a default description:
// "Description not provided".
pub fn easy_ticket(title: String, description: String, status: Status) -> Ticket {
/* TODO */
}
#[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, String> {
if title.is_empty() {
return Err("Title cannot be empty".to_string());
}
if title.len() > 50 {
return Err("Title cannot be longer than 50 bytes".to_string());
}
if description.is_empty() {
return Err("Description cannot be empty".to_string());
}
if description.len() > 500 {
return Err("Description cannot be longer than 500 bytes".to_string());
}
Ok(Ticket {
title,
description,
status,
})
}
pub fn title(&self) -> &str {
&self.title
}
pub fn description(&self) -> &str {
&self.description
}
pub fn status(&self) -> &Status {
&self.status
}
}
答案:
pub fn easy_ticket(title: String, description: String, status: Status) -> Ticket {
match Ticket::new(title.clone(), description, status.clone()) {
Ok(ticket) => ticket,
Err(error) => {
if error.contains("Description") {
Ticket::new(title, "Description not provided".to_string(), status).unwrap()
} else {
panic!("{error}");
}
}
}
}
有两个难点,一个是.clone()
什么时候写,另外一个是用error.contains("Description")
追踪错误。
这一节的内容就先到这结束了。
阅读剩余
版权声明:
作者:CN059
链接:https://www.cn059.com/2025/09/16/39%e3%80%81unwarp%ef%bc%88%e6%8b%86%e5%b0%81%ef%bc%89.html
文章版权归作者所有,未经允许请勿转载。
THE END