【05】RUST错误处理

发布于:2025-02-15 ⋅ 阅读:(34) ⋅ 点赞:(0)

错误处理

建议是尽量用Result由调用者自行决定是否恢复,不恢复也可直接在Err中调用panic。代码分支不可能走的分支可panic。

需要panic的情况:

  1. 有害状态:当一些假设、保证、协议或不可变性被打破的状态,例如无效的值、自相矛盾的值或者被传递了不存在
    的值
  2. 非预期行为,比如:不应该走的分支,不遵循契约(contracts)的函数输入
  3. 后续可能每一步都需要判断错误
  4. 没办法处理错误的,比如:调用外部库出现的无法规避的panic
  5. 实例、代码原型、测试

panic

内存越界问题,运行到此处程序会退出。

  • 展开退出(默认)
    • 回溯栈并清理函数数据
  • 直接终止,需要在Cargo.toml文件中[profile.release]配置panic = 'abort'
    • 不清理直接退出

代码

panic!("错误提示信息"); //运行到此处,会提示错误行,打印错误提示信息

运行

可以通过设置环境变量RUST_BACKTRACE为非0值,调用生成的backtrace,让panic打印调用堆栈信息

RUST_BACKTRACE=1 cargo run

Resut

官方的文档是先介绍的Result,但是个人觉得这个放在泛型后才ok。而且其本质就是一个泛型,封装了各种方法来处理Ok与Err的不同分支。貌似没必要单独拉出来。

处理可恢复错误,程序可以继续运行。成功时候返回Ok实例,失败时返回包含错误信息的Err实例。

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

具体的例子

use std::fs::File;
fn main() {
	let greeting_file_result = File::open("hello.txt");
	let greeting_file = match greeting_file_result {
		Ok(file) => file,
		Err(error) => panic!("Problem opening the file: {error:?}"),
	};
}

Result中的一些方法介绍

let greeting_file = File::open("hello.txt").unwrap();
// Ok时,unwrap()返回Ok中的值
// Err时,unwrap()调用panic!

let greeting_file = File::open("hello.txt").expect("hello.txt should be included in this project");
// 与unwrap()类似,但是会传递信息给panic!

传播错误

就是把Result结果作为函数返回。

运算符

可使用?运算符简写,该运算符会调用form并转换错误,无需增加额外代码。

  • 返回Ok:程序继续运行
  • 当出现Err:Err作为整个函数返回值提前返回
  • 只能在函数返回Result类型时候才能,调用?运算符
  • 也可以用于OptionSomeNone分支的简写
use std::fs::File;
use std::io::{self, Read};

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

?可以进行链式调用

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