Rust 错误处理

1. panic异常

可以配置在release版本中,发生panic时是否中止运行

cargo.toml文件中

[package]
name = "demo"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

[profile.release]
panic= 'abort'

1.1自定义panic

测试代码:

fn main(){
    panic!("不可恢复异常!");
}

运行结果:

thread 'main' panicked at '不可恢复异常!', src/main.rs:6:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

1.2 越界panic

测试代码:

fn main() {
    let v = vec![1, 2, 3];
    v[4];
}

运行结果:

thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 4', src/main.rs:7:1
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

1.3 显示调用栈

先设置环境变量RUST_BACKTRACE=1后,再运行就可以显示调用栈信息

xuanwenchao@bogon demo % export RUST_BACKTRACE=1
xuanwenchao@bogon demo % cargo run              
    Finished dev [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/demo`
thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 4', src/main.rs:7:1
stack backtrace:
   0: rust_begin_unwind
             at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/panicking.rs:575:5
   1: core::panicking::panic_fmt
             at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/panicking.rs:64:14
   2: core::panicking::panic_bounds_check
             at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/panicking.rs:147:5
   3: <usize as core::slice::index::SliceIndex<[T]>>::index
             at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/slice/index.rs:260:10
   4: core::slice::index::<impl core::ops::index::Index<I> for [T]>::index
             at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/slice/index.rs:18:9
   5: <alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::index
             at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/alloc/src/vec/mod.rs:2727:9
   6: demo::main
             at ./src/main.rs:7:1
   7: core::ops::function::FnOnce::call_once
             at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/ops/function.rs:507:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
xuanwenchao@bogon demo % 

2. 用Result做错语处理

2.1 Result枚举定义

Result定义如下:

pub enum Result<T, E> {
    /// Contains the success value
    #[lang = "Ok"]
    #[stable(feature = "rust1", since = "1.0.0")]
    Ok(#[stable(feature = "rust1", since = "1.0.0")] T),

    /// Contains the error value
    #[lang = "Err"]
    #[stable(feature = "rust1", since = "1.0.0")]
    Err(#[stable(feature = "rust1", since = "1.0.0")] E),
}

2.2 打开文件错语的处理

打开一个文件,如果文件存在得到句柄,如果不存在可以自定义处理方式

use std::fs::File;
fn main() {
    let mut f = match File::open("test.txt") {
        Ok(f) => f,
        Err(e) => {
            panic!("打不开文件!{}", e)
        }
    };
}    

运行结果

thread 'main' panicked at '打不开文件!No such file or directory (os error 2)', src/main.rs:9:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

2.3 打开文件失败则创建

use std::fs::File;
use std::io::{ErrorKind, Read};
fn main() {
    let mut f = match File::open("test.txt") {
        Ok(f) => f,
        Err(e) => match e.kind() {
            ErrorKind::NotFound => match File::create("test.txt") {
                Ok(f1) => f1,
                Err(e1) => panic!("创建文件也不行!{:?}", e1),
            },
            _other_error=>panic!("其它原因,不处理!")
        },
    };

    let mut ss = String::new();
    f.read_to_string(&mut ss).expect("error!");
}    

3. 使用闭包操作文件

unwrap: mactch表达式的快捷方法:
如果Result结果Ok,返回Ok里边的值
如果Result结果Err, 调用panic!宏

4. 定义一个返回Result的函数

use std::fs::File;
use std::io::{self, Read};

fn main() {
    let user_name = match read_username_from_file() {
        Ok(name) => println!("用户名:{}", name),
        Err(e) => panic!("读取失败!"),
    };
}

fn read_username_from_file() -> Result<String, io::Error> {
    let f = File::open("test.txt");
    let mut f = match f {
        Ok(f1) => f1,
        Err(e1) => return Err(e1),
    };

    //查找用户名的位置,然后读取,此处省略
    let mut s = String::new();
    f.read_to_string(&mut s)?;
    Ok(s)

其中下边两行代码

    let f = File::open("test.txt");
    let mut f = match f {
        Ok(f1) => f1,
        Err(e1) => return Err(e1),
    };

中以用这种问号结尾的方式来代替,出错时也会自动返回Err(e1),成功就将Ok中的参数赋给f

    let f = File::open("test.txt")?;

5. ?和from

Trait std::convert::From 用于错语之间的转换
当以问结尾,发生错误时,会自动调用from函数将错误转换为需要的错语类型
上边读取用户名的函数可以简化为:

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

你可能感兴趣的:(Rust,rust,开发语言,后端)