初面网初面网

错误处理

Rust中分成可恢复错误和不可恢复错误。

可恢复错误,程序员能够操作,但是程序能够继续运行。比如文件读写中检测到文件被占用,无法读取或写入。

不可恢复错误,代码本身就有错误,比如妄图向一个不存在的文件中写入内容,或者是访问数组长度之外的位置。

可恢复错误用Result<T,E>类进行处理;不可恢复错误用panic!宏处理。

panic!("Error!");

// panic最终操作是终止程序并交由系统收拾残留内存,还是回溯结构并清理沿途残留数据,可以在Cargo.toml文件中设置
// [profile.release]  意味着在生产环境中
// panic = 'abort'  // abort,意味着立即终止程序,由OS打扫

可恢复错误的用例:

use std::fs::File;

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

fn main() {
  let f = File::open("hello.txt");
  match f {
    Ok(file) => {
      println!("File opened successfully.");
    },
    Err(err) => {
      println!("Failed to open the file.");
    }
  }
}

可以将可恢复错误按不可恢复错误一样处理,使用unwrap或expect。expect可以指定错误消息,unwrap则不行。

use std::fs::File;

fn main() {
  let f1 = File::open("hello.txt").unwrap();
  let f2 = File::open("hello.txt").expect("Failed to open.");
}

编写错误处理函数

fn f(i: i32) -> Result<i32, bool> {
  if i >= 0 { Ok(i) }
  else { Err(false) }
}

fn g(i: i32) -> Result<i32, bool> {
  let t = f(i)?;
  // ?符实际作用是将 Result 类非异常的值直接取出
  // ?符仅限于Result<T,E>这种,且E的类型与?处理的Result的E的类型一致
  Ok(t) // 因为确定 t 不是 Err, t 在这里已经是 i32 类型
}

fn main() {
  let r = g(10000);
  if let Ok(v) = r {
    println!("Ok: g(10000) = {}", v);
  } else {
    println!("Err")
  }
}

使用kind获取Err类型

use std::io;
use std::io::Read;
use std::fs::File;

fn read_text_from_file(path: &str) -> Result<String, io::Error> {
  let mut f = File::open(path)?;
  let mut s = String::new();
  f.read_to_string(&mut s)?;
  Ok(s)
}

fn main() {
  let str_file = read_text_from_file("hello.txt");
  match str_file {
    Ok(s) => println!("{}", s),
    Err(e) => {
      match e.kind() {
        io::ErrorKind::NotFound => {
          println!("No such file");
        },
        _ => {
          println!("Cannot read the file");
        }
      }
    }
  }
}

简单版

use std::io;
fn divide(a: f64, b: f64) -> Result<f64, String> {
  if b == 0.0 {
    Err(String::from("Cannot divide by Zero"))
  } else {
    Ok( a/b )
  }
}

fn main(){
  match divide(10.0, 0.0) {
    OK(result) => println!("Result: {}", result),
    Err(error) => println!("Error: {}", error),
  }
  
  let mut input = String:new();
  println!("Enter your name:");
  io::stdin()
      .read_line(&mut input)
      .expect("Failed to read input");
  let name = input.trim();
  println!("Hello, {}!", name);
}

更新于 2026/6/11