当前位置:   article > 正文

Rust编程-错误处理_rust `okwrap` is implemented for `result`

rust `okwrap` is implemented for `result`

错误分类:

        可恢复错误:Result<T,E>。文件查找不存在,可以重试。

        不可恢复错误:panic!()宏。访问数组越界,会发生panic

不可恢复错误:

       

        处理方式:

                栈展开:Rust会沿着调用栈的反向顺序遍历所有调用函数,并依次清理这些函数中的数据。

                立即终止:直接结束程序且不进行任何清理工作,程序所使用过的内存只能由操作系统来进行回收。

                                Cargo.toml文件中添加配置:

  1. [profile.release]
  2. panic = 'abort'

                                在最终生成包里会采用立即终止程序

        获取回溯信息:

                回溯信息可能包含Rust核心库、标准库和第三方库

                RUST_BACKTRACE=1 cargo run

可恢复的错误:

        

  1. num Result<T, E> {
  2. Ok(T),
  3. Err(E),
  4. }

        T代表了Ok变体中包含的值类型;E则代表了Err变体中包含的错误类型

         Result枚举及其变体已经通过预导入模块被自动地引入当前作用域中

         可以根据不同的错误原因,做出不同的处理:

                

  1. use std::fs::File;
  2. use std::io::ErrorKind;
  3. let f = File::open("hello.txt");
  4. let f = match f {
  5. Ok(file) => file,
  6. Err(error) => match error.kind() { // error.kind() 返回的是枚举类型;该枚举类型需要引入标准库的ErrorKind
  7. ErrorKind::NotFound => match File::create("hello.txt") {
  8. Ok(fc) => fc,
  9. Err(e) => panic!("Tried to create file but there was a problem: {:?}", e),
  10. },
  11. other_error => panic!("There was a problem opening the file: {:?}", other_error), // 这里使用了other_error,表示不再穷举,对剩余的情况的统一处理
  12. },
  13. };

File::open返回的Err变体中的错误值类型,是定义在某个标准库中的结构体类型:io::Error。这个结构体拥有一个被称作kind的方法,调用它来获得io::ErrorKind值。 

 ErrorKind枚举:

  1. enum ErrorKind {
  2. NotFound,
  3. PermissionDenied,
  4. DiskFull,
  5. }

 利用闭包简化match嵌套:

  1. let f = File::open("hello.txt").map_err(|error| { // 这里调用map_err()函数,里面是闭包函数
  2. if error.kind() == ErrorKind::NotFound {
  3. File::create("hello.txt").unwrap_or_else(|error| { // 这里调用unwrap_or_else()函数,里面是闭包
  4. panic!("Tried to create file but there was a problem: {:?}", error);
  5. })
  6. } else {
  7. panic!("There was a problem opening the file: {:?}", error);
  8. }
  9. });

  这里使用了两个函数map_err()和unwrap_or_else():

        map_err(): 

                map_err 方法用于将错误类型从一个类型转换为另一个类型。它接收一个闭包(closure),该闭包将原始错误类型转换为新的错误类型。map_err 通常用于在错误处理链中将错误类型统一化,以便更方便地处理错误。

                代码中error.kind() 将io::Error转换成io::ErrorKind, 然后进行比较。

                

  1. use std::fs::File;
  2. use std::io::Error;
  3. let file = File::open("non_existent_file.txt").map_err(|err| {
  4. Error::new(err.kind(), "文件不存在")
  5. });

使用 map_err 将 io::Error 转换为自定义的 Error 类型。 

        unwrap_or_else():

    unwrap_or_else 方法用于处理 Option 或 Result 类型的值。如果值是 Some 或 Ok,则返回其中的值;否则,执行提供的闭包,并返回闭包的返回值。

  1. let value = Some(42);
  2. let result = value.unwrap_or_else(|| 0); // 成功返回42,失败返回0
  3. println!("result: {}", result); // 输出:result: 42
  4. let none_value: Option<i32> = None;
  5. let result = none_value.unwrap_or_else(|| 0);
  6. println!("result: {}", result); // 输出:result: 0

        快速触发panic的两个方法:(中断程序继续运行

                unwrap(): 当Result的返回值是Ok变体时,unwrap就会返回Ok内部的值。而当Result的返回值是Err变体时,unwrap则会替我们调用panic! 宏

                expect(): 基于unwrap函数,expect("xxx") 可以传入参数,表明错误的具体原因

错误传播:return or ?

        

  1. fn read_username_from_file() -> Result<String, io::Error> {
  2. let f = File::open("hello.txt");
  3. let mut f = match f {
  4. Ok(file) => file,
  5. Err(e) => return Err(e), // 通过return返回Err(e) ,将错误返回给调用者
  6. };
  7. let mut s = String::new();
  8. match f.read_to_string(&mut s) {
  9. Ok(_) => Ok(s),
  10. Err(e) => Err(e), // 返回Err,返回给调用者。由于这里是函数的最后一个表达式,所以我们不再需要显式地添加return
  11. }
  12. }
        ?运算符:

                传播错误的模式在Rust编程中非常常见,所以Rust专门提供了一个问号运算符(?)来简化它的语法。

                将?放置于Result值。假如这个Result的值是Ok,那么包含在Ok中的值就会作为这个表达式的结果返回并继续执行程序。假如值是Err,那么这个值就会作为整个程序的结果返回,如同使用了return一样将错误传播给调用者。

              使用了?运算符的函数必须返回Result、Option或任何实现了std::ops::Try的类型

  1. fn read_username_from_file() -> Result<String, io::Error> { // 返回类型是Result<String,io::Error>
  2. let mut s = String::new();
  3. File::open("hello.txt")?.read_to_string(&mut s)?; //这里是加分号
  4. Ok(s)
  5. }

错误类型:

        std::io::Error: 表示I/O错误的类型。它包含一个ErrorKind和一个可选的错误消息,用于表示I/O操作过程中的错误,例如文件I/O,网络I/O或其他类型的I/O。

        std::io::ErrorKind: 它是一个枚举,表示I/O错误的类型。它的枚举变体有NotFound,PermissionDenied,ConnectionRefused和其他类型。ErrorKind用于对I/O错误的类型进行分类,使其更容易处理和响应不同类型的错误。

        std::error::Error: 表示一个泛型的错误类型的trait。它提供一种将错误类型转换为字符串的方法,从而可以向用户显示错误消息。Error是io::Error的超trait。意味着,上线了io::Error也实现了Error。

        

  1. use std::error::Error;
  2. fn main() -> Result<(), Box<dyn Error>> { // 允许将错误转换成字符串显示给用户
  3. let file = File::open("non_existent_file.txt")?;
  4. Ok(())
  5. }

何时panic!:

        代码一旦发生panic,就再也没有恢复的可能了.

        返回一个Result值时,你就将这种选择权交给了调用者

        通过人工检查确保代码永远不会出现Err变体,那就使用unwrap。unwrap内部是调用panic!()宏。

        某个错误可能会导致代码处于损坏状态时,使用panic来处理错误。损坏状态意味着设计中的一些假设、保证、约定或不可变性出现了被打破的情形。比如,当某些非法的值、自相矛盾的值或不存在的值被传入代码中

        假如错误是可预期的,那么就应该返回一个Result而不是调用panic!

        

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/847216
推荐阅读
相关标签
  

闽ICP备14008679号