可恢复异常

RUST中的大多数错误处理 都是通过 Option Result 类型或者是该类型的扩展实现的;

该类型本质上是通过RUST 对于Enum基元类型,可以包装 内部类型的能力实现的

pub enum Option<T> {
    None,
    Some(T),
}

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

两种类型 都是std 标准库提供的自定义类型 并非RUST 内置类型

简单的enmum匹配

先熟悉一些 枚举类型的基本匹配方法 ,option 和 Result 同样都适用

#[derive(Debug)]
enum Color {
    RED,
    GREEN,
}

#[derive(Debug)]
struct Apple(Color);

fn main() {
    let color1 = Color::GREEN;
    //match 匹配所有可能值 
    let a = match color1 {
        Color::RED => {
            println!("color is RED");
            Apple(Color::RED)
        },
        Color::GREEN => {
            println!("color is GREEN");
            Apple(Color::GREEN)
        },
    };
    println!("{:?}",a);

    //if let 可以单个匹配 
    let color1 = Color::RED;

    if let Color::RED = color1 {
            println!("color is RED");
    }
}

Option

option 是一个枚举类型,该类型由两个 变体: None(不带值) Some(附带一个泛型)

pub enum Option<T> {
    None,
    Some(T),
}

最简单的使用: 说明错误原因

fn main() {
    let mut op = Option::None;
    op = Option::Some(10);

    let mut op =  Option::None;
}

None 和Some 已经被rust 通过prelude 导入

fn main() {
    let mut op = None;
    op = Some(10);
}

应用1:大量用于返回值类型

#[derive(Debug)]
struct Dog {
    name: String,
}

struct DogHome {
    dogs: Vec<Dog>,
}

impl DogHome {
    fn put_dog(&mut self, name: &str) {
        self.dogs.push(Dog{name: name.to_string()});
    }

    fn get_dog(&mut self, name: &str) -> Option<&Dog> {
        for dog in &self.dogs {
            if dog.name == name {
                    return Some(dog);
            }
        }
        None
    }
}

fn main(){
    let mut doghome =DogHome{dogs: Vec::new()};
    doghome.put_dog("john");

    let john = doghome.get_dog("john");
    println!("{:?}",john);

    let jack = doghome.get_dog("jack");
    println!("{:?}",jack);
}

应用2:用于结构体中,之前的链表实验我们已经见到过了

Option除了适用enum的match 和 if let 还提供了unwrap和except 方法,区别是如果值为None,会触发panic

一般情况下,会认为panic的解压不安全,在以下两种情况下建议使用:

  • 明确了值不可能为None
  • 确实希望产生panic
#[derive(Debug)]
struct Dog {
    name: String,
}

struct DogHome {
    dogs: Vec<Dog>,
}

impl DogHome {
    fn put_dog(&mut self, name: &str) {
        self.dogs.push(Dog{name: name.to_string()});
    }

    fn get_dog(&mut self, name: &str) -> Option<&Dog> {
        for dog in &self.dogs {
            if dog.name == name {
                    return Some(dog);
            }
        }
        None
    }
}

fn main(){
    let mut doghome =DogHome{dogs: Vec::new()};
    doghome.put_dog("john");

    let john = doghome.get_dog("john");
    println!("{:?}",john.unwrap());

    let jack = doghome.get_dog("jack");
    println!("{:?}",jack.expect("jack is none"));
}

Result

RESULT 也是一个枚举类型,和option 类似 该类型也由两个 变体: OK(附带一个泛型) Err(附带一个泛型) 构成

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

从变体名称上可以直观看到,OK和Err 分别表示成功和失败的两种情况 该类型相比Option 从使用场景更加固定一些,那就是函数的返回值

说明代码问题

fn main() {
    let result = Ok(32);
    let result2 = Err("invalid param");
}

很多标准库提供的返回值 都是result 类型 说明下面代码问题原因

use std::path::Path;

fn main() {
    let path = Path::new("data.txt");
    let file = File::open(&path);
    let mut s = String::new();
    file.read_to_string(&mut s);

    println!("Message : {}",s);
}

第一次修改

use std::path::Path;

fn main() {
    let path = Path::new("data.txt");
    let file = match File::open(&path) {
        Ok(file) => file,
        Err(err) => panic!("Error opening file: {}",err),
    };

    let mut s = String::new();
    let _ = file.read_to_string(&mut s); //主动忽略掉错误处理

    println!("Message : {}",s);
}