美文网首页
Rust编程语言-9-异常处理

Rust编程语言-9-异常处理

作者: onemoremile | 来源:发表于2022-01-11 22:12 被阅读0次

    异常处理

    panic!宏处理不可恢复的异常,程序终止

    fn main() {
        let v = vec![1, 2, 3];
        v[99];
    }
    
    $ cargo run
       Compiling panic v0.1.0 (file:///projects/panic)
        Finished dev [unoptimized + debuginfo] target(s) in 0.27s
         Running `target/debug/panic`
    thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', src/main.rs:4:5
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
    
    

    注意这里的RUST_BACKTRACE=1 环境变量,设置该变量后可以看到详细的报错信息

    $ RUST_BACKTRACE=1 cargo run
    thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', src/main.rs:4:5
    stack backtrace:
       0: rust_begin_unwind
                 at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/panicking.rs:483
       1: core::panicking::panic_fmt
                 at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/panicking.rs:85
       2: core::panicking::panic_bounds_check
                 at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/panicking.rs:62
       3: <usize as core::slice::index::SliceIndex<[T]>>::index
                 at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/slice/index.rs:255
       4: core::slice::index::<impl core::ops::index::Index<I> for [T]>::index
                 at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/slice/index.rs:15
       5: <alloc::vec::Vec<T> as core::ops::index::Index<I>>::index
                 at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/alloc/src/vec.rs:1982
       6: panic::main
                 at ./src/main.rs:4
       7: core::ops::function::FnOnce::call_once
                 at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/ops/function.rs:227
    note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
    
    

    Result<T, E> 来处理可恢复的异常

    #![allow(unused)]
    fn main() {
    enum Result<T, E> {
        Ok(T),
        Err(E),
    }
    }
    

    举个栗子

    use std::fs::File;
    use std::io::ErrorKind;
    
    fn main() {
        let f = File::open("hello.txt");
    
        let f = match f {
            Ok(file) => file,
            Err(error) => match error.kind() {
                ErrorKind::NotFound => match File::create("hello.txt") {
                    Ok(fc) => fc,
                    Err(e) => panic!("Problem creating the file: {:?}", e),
                },
                other_error => {
                    panic!("Problem opening the file: {:?}", other_error)
                }
            },
        };
    }
    

    程序可以运行,但是太多的match了,换种写法(使用闭包closure)

    use std::fs::File;
    use std::io::ErrorKind;
    
    fn main() {
       let f = File::open("hello.txt").unwrap_or_else(|error| {
           if error.kind() == ErrorKind::NotFound {
               File::create("hello.txt").unwrap_or_else(|error| {
                   panic!("Problem creating the file: {:?}", error);
               })
           } else {
               panic!("Problem opening the file: {:?}", error);
           }
       });
    }
    

    更精简的写法

    use std::fs::File;
    fn main() {
        let f = File::open("hello.txt").unwrap();
    }
    
    或者
    let f = File::open("hello.txt").expect("Failed to open hello.txt");
    

    异常的传播Propagating exception

    fn read_username_from_file() -> Result<String, io::Error> {
        let f = File::open("hello.txt");
    
        let mut f = match f {
            Ok(file) => file,
            Err(e) => return Err(e),
        };
    
        let mut s = String::new();
        match f.read_to_string(&mut s) {
            Ok(_) => Ok(s),
            Err(e) => Err(e),
        }
    }
    

    问号操作符?简化异常传播

    #![allow(unused)]
    fn main() {
    use std::fs::File;
    use std::io;
    use std::io::Read;
    
    fn read_username_from_file() -> Result<String, io::Error> {
        let mut f = File::open("hello.txt")?;
        let mut s = String::new();
        f.read_to_string(&mut s)?;
        Ok(s)
    }
    }
    

    可以简化上述代码

    fn read_username_from_file() -> Result<String, io::Error> {
        let mut s = String::new();
        File::open("hello.txt")?.read_to_string(&mut s)?;
        Ok(s)
    }
    

    还可以进一步简化

    use std::fs;
    use std::io;
    
    fn read_username_from_file() -> Result<String, io::Error> {
        fs::read_to_string("hello.txt")
    }
    

    在main() 函数中返回Result,使用了Box<dyn Error>,可以支持多种异常

    use std::error::Error;
    use std::fs::File;
    
    fn main() -> Result<(), Box<dyn Error>> {
        let f = File::open("hello.txt")?;
    
        Ok(())
    }
    
    

    如何决定是否panic!

    如下struct Guess,如果初始化的值超出范围,给出panic!

    #![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编程语言-9-异常处理

          本文链接:https://www.haomeiwen.com/subject/juyicrtx.html