使用 Result 来处理异常

在 Rust 中,可以使用 Result 这个 enum 来处理异常

源码如下:

#![allow(unused)]
fn main() {
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),
}
}

它是一个泛型,有两个类型参数,第一个是成功的类型 T,第二个是失败的类型 E

使用案例

我们可以这样使用它,例如我定义了一个函数,返回 Result

#![allow(unused)]
fn main() {
fn test(flag: bool) -> Result<String,io::Error> {
    if flag {
        let s = String::from("greycode");
        return Ok(s);
    }else{
        return Err(io::Error::new(io::ErrorKind::Other, "customize error"));
    }
}
}

当函数参数传入 true 时,就返回 OK,否则就返回 Err

使用 match 来处理

可以使用 match 匹配 Result 的两种情况

fn main(){
    let s = match test(false) {
        Ok(s) => s,
        Err(e) => panic!("error: {}", e),
    };
    println!("{}", s);
}

使用 unwrap 来处理

可以使用 unwrap 来处理 Result,如果是 Ok,就返回 Ok 的值,如果是 Errunwrap 会自动帮我们调用 panic

fn main(){
    let s = test(false).unwrap();
    println!("{}", s);
}

完整代码

use std::io;

fn main(){
    let s = test(true).unwrap();
    println!("{}", s);

    // let s = match test(true) {
    //     Ok(s) => s,
    //     Err(e) => panic!("error: {}", e),
    // };
    // println!("{}", s);
}

fn test(flag: bool) -> Result<String,io::Error> {
    if flag {
        let s = String::from("greycode");
        return Ok(s);
    }else{
        return Err(io::Error::new(io::ErrorKind::Other, "customize error"));
    }
}

符号 ? 的作用

?unwrap() 类似,可以简化 match 的写法,它的作用是,如果是 Ok,就返回 Ok 的值,如果是 Err,就返回 Err 的值,不会调用 panic

只能用于返回值为 Result 的函数

简化前:

#![allow(unused)]
fn main() {
use std::io;
use std::io::Read;
use std::fs::File;

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::io;
use std::io::Read;
use std::fs::File;

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)
}
}