^(* ̄(oo) ̄)^

  • 首页
  • 博客
  • 文档
  • 网盘
  • 仓库
  • 简介
Keep Learning
  1. 首页
  2. 文档
  3. 正文

Rust Basic 9 - Error Handling

2023年4月24日 718点热度

Rust将错误分为两大类:可恢复和不可恢复的错误。对于可恢复的错误,例如找不到文件错误,我们可能只需要向用户报告问题并重试操作。不可恢复的错误总是 bug 的症状,例如试图访问数组末尾之外的位置,所以我们要立即停止程序。

大多数语言不区分这两种错误,并使用类似于异常的机制来处理。但是Rust没有异常,它使用类型Result<T, E>来处理可恢复的错误,使用 panic! 宏来停止程序执行当遇到不可恢复的错误。本章将先讨论调用 panic! ,然后讨论返回Result<T, E>的值。此外,我们还将探讨在决定是恢复错误还是停止执行时的考虑因素。

panic

当发生恐慌时,程序开始展开,这意味着Rust向上走回堆栈并清理每个函数遇到的数据。然而,这种向上走和清理是很多工作。因此,Rust允许您选择立即中止的方法,这样可以在不清理的情况下结束程序。

 // 发布模式下出现 panic 时中止。 修改Cargo.toml文件
​
[profile.release]
panic = 'abort'

简单的panic!

第一行显示了我们的恐慌消息以及我们源代码中发生恐慌的位置:src/main.rs:2:5表示它是第二行,我们的src/main.rs文件的第五个字符。

使用panic!回溯

访问越界

根据错误提示。设置RUST_BACKTRACE 环境变量以获取导致错误的确切原因的回溯。

可恢复的错误Result

枚举Result的定义:

enum Result<T, E> {
    Ok(T),
    Err(E),
}

打开不存在的文件:

 

创建文件后:

匹配不同的错误

通过代码定位到具体的错误,而非自己去查找、

不使用match

unwrap_or()方法接受一个默认值作为参数,如果Result的值是Ok,则返回其内部的值,如果Result的值是Err,则返回默认值。这个方法适用于错误情况下提供一个固定的默认值的情况。

unwrap_or_else()方法接受一个回调函数作为参数,如果Result的值是Ok,则返回其内部的值,如果Result的值是Err,则调用传递给unwrap_or_else的回调函数,并返回其返回值。回调函数允许对错误情况进行自定义处理。

unwrap and expect

unwrap() 是一种方法,它返回包含的值或在错误时引发错误。它用于您确信结果将是“Ok”的情况,并希望如果不是则崩溃程序。

使用 expect,允许我们选择panic!错误消息。相较于unwrap,expect使用的更多。

传播错误

当一个函数的实现调用可能失败的操作时,与其在函数内部处理错误,您可以将错误返回给调用代码,以便它可以决定如何处理。这称为传播错误,

运行(包含数据):

运行(不存在文件):

此函数可以以更短的方式编写,但是我们首先要手动执行很多操作,以探索错误处理。

?运算符--传播错误快捷方式

以下代码同前文代码作用完全相同

使用立即链接进一步精简代码

使用系统函数(fs::read_to_string)

?可以出现的位置

该?运算符只能用在返回类型与所用值兼容的函数,若尝试在main函数(无返回值时)中使用?是不可以的。

使用?with option<T>

在给定文本中查找第一行的最后一个字符:

如果text是空字符串,则此调用next将返回None,在这种情况下我们使用?停止并None从 返回last_char_of_first_line。如果text不是空字符串,next将返回一个Some包含 中第一行的字符串切片的值text。

chars字符串切片以获取其字符的迭代器。调用last以返回迭代器中的最后一项。

修改main函数来适配?

Box<dyn Error>类型是一个特征对象, 目前可以理解为“任何类型的错误”。?允许在具有错误类型的函数中使用Result 值,因为它允许提前返回任何值。即使此函数的主体将只返回 类型的错误,通过指定,即使返回其他错误的更多代码添加到 的主体,此签名也将继续正确。

当main函数返回Result<(), E>时,如果main返回Ok(()),可执行文件将以0值退出,如果main返回Err值,则将以非0值退出。C语言编写的可执行文件在退出时返回整数:成功退出的程序返回整数0,错误退出的程序返回非0的整数。Rust还从可执行文件中返回整数以与此约定兼容。

main函数可以返回任何实现std::process:: terminate特征的类型,该特征包含一个返回ExitCode的函数报告。有关为自己的类型实现terminate特征的更多信息,参阅标准库文档。

To panic! or Not to panic!

什么使用返回panic?什么时候Result(类似 try-catch)?

在示例、原型代码和测试等情况下,更合适的做法是编写具有panic的代码,而不是返回Result。

个人认为,开发时除了能控制逻辑的代码可以多返回panic。而发布产品时尽量不返回panic,因为会导致程序停止(健壮性低)。

panic的各种情况

  1. 示例、原型代码和测试时,使用panic。

  2. 比编译器掌握更多信息的情况,可以使用Result,结果可控。但如果IP地址字符串来自用户而不是硬编码到程序中,因此确实有失败的可能性,我们肯定希望以Result更稳健的方式处理。.

 

错误处理指南

当代码可能最终处于错误的状态时,让代码返回panic是明智的。

然而,当预期失败时,返回Result比制造恐慌更合适!调用。例如,向解析器提供格式错误的数据或HTTP请求返回指示您已达到速率限制的状态。在这些情况下,返回Result表明失败是调用代码必须决定如何处理的预期可能性。

创建用于验证的自定义类型

猜数字旧版代码:

use rand::Rng;
use std::cmp::Ordering;
use std::io;
​
fn main() {
    println!("Guess the number!");
​
    let secret_number = rand::thread_rng().gen_range(1..=100);
​
    loop {
        // --snip--
​
        println!("Please input your guess.");
​
        let mut guess = String::new();
​
        io::stdin()
            .read_line(&mut guess)
            .expect("Failed to read line");
​
        let guess: i32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };
​
        if guess < 1 || guess > 100 {
            println!("The secret number will be between 1 and 100.");
            continue;
        }
​
        match guess.cmp(&secret_number) {
            // --snip--
            Ordering::Less => println!("Too small!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => {
                println!("You win!");
                break;
            }
        }
    }
}
​

更好的方式:

#![allow(unused)]
fn main() {
pub struct Guess {
    value: i32,
}
​
impl Guess {
    pub fn new(value: i32) -> Guess {
        if value < 1 || value > 100 {
            panic!("Guess value must be between 1 and 100, got {}.", value);
        }
​
        Guess { value }
    }
​
    pub fn value(&self) -> i32 {
        self.value
    }
}
}
​

运行图:

标签: rust rust-basic
最后更新:2023年4月24日

九州安所如

程序员

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

COPYRIGHT © 2023 zhu

鲁ICP备2026022547号