当前位置: 首页 > article >正文

2024 Rust现代实用教程 Error错误处理

文章目录

  • 一、错误处理之:Result、Option以及panic!宏
    • 1.Result
    • 2.Option
    • 3.panic!
  • 二、错误处理之:unwrap()与'?'
    • 1.unwrap()
    • 2.?运算符
  • 三、自定义一个Error类型
  • 参考

一、错误处理之:Result、Option以及panic!宏

Rust中的错误可以分为两种

  • Recoverable error:有返回类型
    (1)返回Result类型
    (2)返回Option类型

  • Unrecoverable type:没有返回类型,直接崩溃
    panicmacro将终止当前线程

1.Result

Result是一个枚举类型,有两个变体:0k和Err。它通常用于表示函数的执行结果,其中ok表示成功的结果,Err表示出现了错误

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

2.Option

·Option也是一个枚举类型,有两个变体:Some和None。它通常用于表示一个可能为空的值。

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

3.panic!

当程序遇到无法继续执行的错误时,可以使用panic!宏来引发恐慌。恐慌会导致程序立即终止,并显示一条错误消息。

Example:

fn divide(a: i32, b: i32) -> Result<f64, String> {
    if b == 0 {
        return Err(String::from("cannot be zero"));
    }
    let a = a as f64;
    let b = b as f64;
    Ok(a / b)
}

fn find_element(array: &[i32], target: i32) -> Option<usize> {
    for (index, element) in array.iter().enumerate() {
        if (*element) == target {
            return Some(index);
        }
    }
    None
}

fn main() {
    // 处理result结果只能使用match
    match divide(1, 2) {
        Ok(number) => println!("{}", number),
        Err(err) => println!("{}", err),
    }

    match divide(1, 0) {
        Ok(number) => println!("{}", number),
        Err(err) => println!("{}", err),
    }

    // option
    let arr = [1, 2, 3, 4, 5];
    match find_element(&arr, 4) {
        Some(index) => println!("found in {}", index),
        None => println!("None"),
    }
    match find_element(&arr, 7) {
        Some(index) => println!("found in {}", index),
        None => println!("None"),
    }
    // panic
    let vec = vec![1, 2, 3, 4, 5];
    vec[43]; //数组越界
}

编译及运行:

 cargo run
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/ch17_error`
0.5
cannot be zero
found in 3
None
thread 'main' panicked at src/main.rs:43:8:
index out of bounds: the len is 5 but the index is 43
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
~/installer/rust/project/ch17_error master x101 
RUST_BACKTRACE=1 cargo run
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/ch17_error`
0.5
cannot be zero
found in 3
None
thread 'main' panicked at src/main.rs:43:8:
index out of bounds: the len is 5 but the index is 43
stack backtrace:
   0: rust_begin_unwind
             at /rustc/1e4f10ba6476e48a42a79b9f846a2d9366525b9e/library/std/src/panicking.rs:665:5
   1: core::panicking::panic_fmt
             at /rustc/1e4f10ba6476e48a42a79b9f846a2d9366525b9e/library/core/src/panicking.rs:75:14
   2: core::panicking::panic_bounds_check
             at /rustc/1e4f10ba6476e48a42a79b9f846a2d9366525b9e/library/core/src/panicking.rs:285:5
   3: <usize as core::slice::index::SliceIndex<[T]>>::index
             at /home/wangji/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/index.rs:304:10
   4: core::slice::index::<impl core::ops::index::Index<I> for [T]>::index
             at /home/wangji/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/index.rs:16:9
   5: <alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::index
             at /home/wangji/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:3344:9
   6: ch17_error::main
             at ./src/main.rs:43:8
   7: core::ops::function::FnOnce::call_once
             at /home/wangji/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

二、错误处理之:unwrap()与’?’

1.unwrap()

注意:该方法并不安全
unwrap()是 Result 和 Option 类型提供的方法之一。它是一个简便的方法,用于获取 Ok 或 Some 的值,如果是 Err 或 None 则会引发 panic

2.?运算符

?用于简化 Result 或 Option 类型的错误传播。它只能用于返回 Result 或Option 的函数中,并且在函数内部可以像使用unwrap()一样访问 Ok 或 Some的值,但是如果是 Err 或 None 则会提前返回

Example:

use std::num::ParseIntError;

fn find_first_even(numbers: Vec<i32>) -> Option<i32> {
    let first_even = numbers.iter().find(|&num| num % 2 == 0)?;
    print!("Option");
    Some(*first_even)
}

// 传递错误
fn parse_numbers(input: &str) -> Result<i32, ParseIntError> {
    let val = input.parse::<i32>()?;
    Ok(val)
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Result<i32, &str>
    let result_ok: Result<i32, &str> = Ok(32);
    let value = result_ok.unwrap();
    println!("{}", value);
    // Result<i32, &str> 直接panic
    // let result_ok: Result<i32, &str> = Err("ff");
    // let value = result_ok.unwrap();
    // println!("{}", value);
    // 使用?
    let result_ok: Result<i32, &str> = Ok(100);
    let value = result_ok?;
    println!("{}", value);

    // 找到第一个偶数
    let numbers = vec![1, 3, 5];
    match find_first_even(numbers) {
        Some(_) => println!("first even 1"),
        None => println!("no such number"),
    }

    match parse_numbers("d") {
        Ok(i) => println!("parsed {}", i),
        Err(err) => println!("failed to parse: {}", err),
    }

    Ok(())
}

编译及运行:

 cargo run
   Compiling ch18_question_unwrap v0.1.0 (/home/wangji/installer/rust/project/ch18_question_unwrap)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.23s
     Running `target/debug/ch18_question_unwrap`
32
100
no such number
failed to parse: invalid digit found in string

三、自定义一个Error类型

1.定义错误类型结构体:创建一个结构体来表示你的错误类型,通常包含一些字段来描述错误的详细信息。
2.实现 std::fmt::Display trait:实现这个 trait以定义如何展示错误信息。这是为了使错误能够以人类可读的方式打印出来。
3.实现 std::error::Error trait:实现这个 trait以满足Rust的错误处理机制的要求。

#[derive(Debug)]
struct MyError {
    detail: String,
}

impl std::fmt::Display for MyError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "Custom Error: {}", self.detail)
    }
}

impl std::error::Error for MyError {
    fn description(&self) -> &str {
        &self.detail
    }
    // &String String&自动转=> &str 字符串字面量
}

fn func() -> Result<(), MyError> {
    Err(MyError {
        detail: "CustomError".to_owned(),
    })
    // Ok(())
}

// 等价于fn main()->Result<(), MyError>
// 所有实现std::error::Error 的东西,都可以使用Box<dyn std::error::Error>进行返回
fn main() -> Result<(), Box<dyn std::error::Error>> {
    match func() {
        Ok(_) => println!("func ok"),
        Err(err) => println!("Error: {}", err),
    }
    func()?;
    println!("oo"); //以前前面?的原因,且返回的是Err,这里则不会输出
    Ok(())
}

编译及运行

 cargo run
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.05s
     Running `target/debug/ch19_custom_err`
Error: Custom Error: CustomError
Error: MyError { detail: "CustomError" }

参考

  • 2024 Rust现代实用教程

http://www.kler.cn/a/376382.html

相关文章:

  • iptables面试题
  • 终于把DETR搞懂了!Detection Transformer架构详解及使用方法说明
  • 基于双向长短期记忆网络(BiLSTM)的时间序列数据预测,15个输入1个输出,可以更改数据集,MATLAB代码
  • 【NOIP普及组】 FBI树
  • gitee 使用 webhoot 触发 Jenkins 自动构建
  • HarmonyOS:UIAbility组件概述
  • 【tomcat系列漏洞利用】
  • 原生html+js+css+php多图上传带预览可增删判断图片大小和后缀
  • 用100行python代码制作俄罗斯方块游戏,俄罗斯方块游戏教程-附完整代码
  • ros与mqtt相互转换
  • NuGet Next发布,全新版私有化NuGet管理
  • RabbitMQ的路由模式
  • MySQL — 事务 (o゚▽゚)o
  • 【运动的&足球】足球运动员球守门员裁判检测系统源码&数据集全套:改进yolo11-DBBNCSPELAN
  • Django 5企业级Web应用开发实战-日志
  • 前端表格复制粘贴自动根据标识进行填充
  • Python CGI编程-cookie的设置、检索
  • Jenkins面试整理-Jenkins Pipeline 是什么?
  • 「面试必背」Linux面试题(2024最新版)
  • 【LeetCode每日一题】——LCP 07.传递信息
  • OpenCV最详细入门教程
  • linux_c++GDB环境搭建(一)
  • 计算机网络803-(5)运输层
  • 【JavaEE初阶】网络原理(5)
  • 受限玻尔兹曼机(RBM):构成 DBN 的基本单元
  • GeoSever发布图层(保姆姬)