Rust 学习笔记:错误处理

《Rust权威指南》学习笔记(二) Rust编程语言语法知识点 阅读详情

Rust 学习笔记:错误处理

错误在软件中是不可避免的,所以 Rust 有很多特性可以处理出错的情况。

Rust 将错误分为两大类:可恢复的和不可恢复的错误。对于可恢复的错误,我们可能报告该错误并重试操作;对于不可恢复的错误,我们希望立即停止程序。

大多数语言不区分这两种错误,使用异常等机制进行处理。Rust 没有异常,类型为 Result<T, E> 表示可恢复的错误,而 panic! 宏在程序遇到不可恢复的错误时停止执行。

不可恢复的错误

在实践中,有两种方法可以引起 panic:

  • 采取导致代码 panic 的操作(例如访问超过结束的数组)
  • 显式调用 panic! 宏

默认情况下,panic 将打印一条失败消息,沿着堆栈返回并清理遇到的每个函数的数据,最后退出。该情况下,Rust 在 panic 发生时显示调用堆栈,以便更容易地跟踪 panic 的来源。

还有一种情况,在 Cargo.toml 中的 [profile] 部分中添加 panic = 'abort',设置在 panic 时立即中止,这将在不进行清理的情况下结束程序。

[profile.release]
panic = 'abort'

示例 1:

fn main() {
    panic!("crash and burn");
}

调用 panic 会导致最后两行中包含的错误消息,显示了我们的 panic 消息和源代码中发生 panic 的位置。

在这里插入图片描述
示例 2:

fn main() {
    let v = vec![1, 2, 3];

    v[99];
}

如果试图在一个不存在的索引上读取一个元素,Rust 将停止执行并 panic。

在这里插入图片描述

在 C 语言中,试图读取超出数据结构末端的数据是未定义的行为。你可能会得到内存中与数据结构中那个元素对应的位置,即使内存不属于那个结构。这被称为缓冲区过读,如果攻击者能够以这样一种方式操纵索引,从而读取存储在数据结构之后的不允许他们读取的数据,则可能导致安全漏洞。

在这里插入图片描述

Rust 还提醒我们:可以设置 RUST_BACKTRACE 环境变量(为任意不为 0 的值),以获得导致错误的确切回溯信息。

回溯是所有被调用的函数的列表。Rust 中的回溯和其他语言中的一样:从顶部开始读,直到看到自己写的文件,这就是问题产生的地方。该点上方的行是代码调用过的代码,下面几行代码调用了您的代码。

注意,这里使用 Windows 的 PowerShell 是无法运行的,可以切换 git bash 运行即可。

在这里插入图片描述

backtrace 的第 5 行指向项目中导致问题的行:src/main.rs 的第 4 行。如果我们不想让程序陷入恐慌,就应该从提到我们编写的文件的第一行所指向的位置开始调查。

根据操作系统和 Rust 版本的不同,backtrace 的确切输出可能会有所不同。

带有结果的可恢复错误

大多数错误并不严重到需要程序完全停止。有时,当一个函数失败时,它的原因很容易解释和响应。例如,如果您尝试打开一个文件,但由于该文件不存在而导致该操作失败,那么您可能希望创建该文件,而不是终止该进程。

Result 枚举被定义为有两个变体,Ok 和 Err,如下所示:

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

T 和 E 是泛型类型参数,T 表示成功情况下在 Ok 变量中返回的值的类型,而 E 表示失败情况下在 Err 变量中返回的错误的类型。我们可以在许多不同的情况下使用 Result 类型及其上定义的函数,其中我们希望返回的成功值和错误值可能不同。

让我们调用一个返回 Result 值的函数,因为该函数可能会失败:

use std::fs::File;

fn main() {
    let greeting_file_result = File::open("hello.txt");
}

File::open 的返回类型是 Result<T, E>。泛型参数 T 是由 File::open 的实现用成功值 std::fs::File 的类型填充的,它是一个文件句柄。错误值中使用的 E 类型为 std::io:: error。File::open 函数需要有一种方法来告诉我们它是成功还是失败,同时给我们文件句柄或错误信息。这个信息正是 Result 枚举所传达的。

在 File::open 成功的情况下,变量 greeting_file_result 中的值将是一个包含文件句柄的 Ok 实例。在失败的情况下,greeting_file_result 中的值将是Err的一个实例,其中包含有关发生的错误类型的更多信息。

使用 match 能很好地处理 Result<T, 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:?}"),
    };
}

当结果为 Ok 时,这段代码将返回 Ok 变量的内部文件值,然后我们将该文件句柄值赋给变量 greeting_file。匹配之后,我们可以使用文件句柄进行读写。

当结果为 Err 时,我们选择调用 panic! 宏输出错误信息。

匹配不同的错误

我们希望针对不同的失败原因采取不同的行动。如果 File::open 因为文件不存在而失败,我们希望创建文件并返回新文件的句柄。如果 File::open 由于任何其他原因而失败,我们仍然希望代码 panic。

use std::fs::File;
use std::io::ErrorKind;

fn main() {
    let greeting_file_result = File::open("hello.txt");

    let greeting_file = match greeting_file_result {
        Ok(file) => file,
        Err(error) => match error.kind() {
            ErrorKind::NotFound => match File::create("hello.txt") {
                Ok(fc) => fc,
                Err(e) => panic!("Problem creating the file: {e:?}"),
            },
            _ => {
                panic!("Problem opening the file: {error:?}");
            }
        },
    };
}

File::open 在 Err 变量中返回的值的类型是 io::Error,它是标准库提供的结构体。这个结构体有一个方法 kind,我们可以调用它来获取 io::ErrorKind 的值。

枚举 io::ErrorKind 由标准库提供,具有代表 io 操作可能导致的不同类型错误的变体。我们想使用的变体是 ErrorKind::NotFound,它表示我们试图打开的文件还不存在。这种情况下,我们尝试用 file::create 创建文件。但是,由于 File::create 也可能失败,我们还需要在内部匹配表达式中添加另一个 match:创建成功时,同样返回文件句柄;无法创建时,打印一条不同的错误消息。

出现错误时 panic 的快捷方式:unwrap 和 expect

使用 match 可能有点冗长,并且不能很好地传达意图。Result<T, E> 类型在其上定义了许多帮助器方法来执行各种更具体的任务。

unwrap 方法是一个快捷方法,如果 Result 值是 Ok 变体,则 unwrap 将返回 Ok 内部的值;如果 Result 是 Err 变体,unwrap 将调用 panic! 宏。

use std::fs::File;

fn main() {
    let greeting_file = File::open("hello.txt").unwrap();
}

如果我们在没有 hello.txt 文件的情况下运行这段代码,我们将看到 panic 发出的错误消息:

在这里插入图片描述

使用 expect 可以自定义 panic 错误信息,并使跟踪恐慌的来源更容易。

expect 的语法是这样的:

use std::fs::File;

fn main() {
    let greeting_file = File::open("hello.txt")
        .expect("hello.txt should be included in this project");
}

我们使用 expect 的方式与 unwrap 相同:返回文件句柄或调用 panic! 宏。expect 在调用 panic! 宏时打印我们传递的参数。

在这里插入图片描述

unwrap 更常用,因为可以在调试中使用更多的信息。

传播错误

当函数的实现调用可能失败的东西时,可以将错误返回给调用代码。这被称为传播错误,并为调用代码提供了更多的控制。

示例:

use std::fs::File;
use std::io::{self, Read};

fn read_username_from_file() -> Result<String, io::Error> {
    let username_file_result = File::open("hello.txt");

    let mut username_file = match username_file_result {
        Ok(file) => file,
        Err(e) => return Err(e),
    };

    let mut username = String::new();

    match username_file.read_to_string(&mut username) {
        Ok(_) => Ok(username),
        Err(e) => Err(e),
    }
}

让我们先看看函数的返回类型:Result<String, io::Error>。这意味着函数返回一个 Result<T, E> 类型的值,其中泛型参数 T 已经用具体类型 String 填充,泛型类型E已经用具体类型 io::Error 填充。

如果这个函数成功,调用这个函数的代码将收到一个 Ok 值,该值包含一个 String——这个函数从文件中读取的用户名。如果此函数遇到任何问题,调用代码将接收一个 Err 值,该值包含 io::Error 的实例,该实例包含有关问题所在的更多信息。

之所以选择 io::Error 作为函数的返回类型,是因为在函数体中调用的 File::open 函数和 read_to_string 方法这两个可能失败的操作返回的错误值的类型恰好是 io::Error。

这种传播错误的模式在 Rust 中非常常见,因此 Rust 为了方便起见提供了问号操作符 ? 。

传播错误的快捷方式:? 操作符

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

? 放置在 Result 值之后,其工作方式与之前为处理 Result 值而定义的匹配表达式几乎相同。如果 Result 的值为Ok,则该表达式将返回 Ok 中的值,程序将继续执行。如果该值为 Err,则整个函数将返回 Err,就像我们使用了 return 关键字一样,因此错误值将传播到调用代码。

? 操作符消除了大量的样板文件,使这个函数的实现更简单。我们甚至可以通过在 ? 之后立即链接方法调用来进一步缩短代码:

use std::fs::File;
use std::io::{self, Read};

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

代码还能更短吗?当然可以!

将文件读入字符串是一种相当常见的操作,因此标准库提供了方便的 fs::read_to_string 函数,该函数打开文件,创建一个新的 String,读取文件的内容,将内容放入该 String并返回。

最终,函数被简化成了 one line code:

use std::fs;
use std::io;

fn read_username_from_file() -> Result<String, io::Error> {
    fs::read_to_string("hello.txt")
}

哪里可以使用 ? 操作符

? 操作符只能在返回类型与使用 ? 的值兼容的函数中使用,即 Result 类型。

让我们看看一个错误示例:

use std::fs::File;

fn main() {
    let greeting_file = File::open("hello.txt")?;
}

在这里插入图片描述

这段代码打开一个文件,可能会失败。? 操作符在 File::open 返回的 Result 值之后,但是这个主函数的返回类型是 (),而不是 Result。

这个错误指出我们只允许使用 ? 返回 Result、Option 或其他实现 FromResidual 的类型的函数中的操作符。

要修复这个错误,有两种选择。一种选择是更改函数的返回类型,使其与使用的值兼容。只要没有限制,就继续操作。另一种选择是使用 match 或 Result<T, E> 方法之一,以任何合适的方式处理 Result<T, E>。

? 操作符在Option<T>上调用时的行为与在 Result<T, E> 上调用时的行为相似:如果值为 None,则在该点将提前从函数返回 None。如果值是 Some,则 Some 内的值是表达式的结果值,函数继续执行。

下面给出一个示例:

fn last_char_of_first_line(text: &str) -> Option<char> {
    text.lines().next()?.chars().last()
}

这个函数返回 Option<char>,因为这里可能有字符,但也可能没有。

如果 text 不是空字符串,next 将返回一个 Some 值,其中包含 text 中第一行的字符串切片。? 提取字符串切片,然后调用该字符串切片上的 chars 来获取其字符的迭代器,调用 last 来返回迭代器中的最后一项。

注意,可以使用 ? 操作符对返回 Result 的函数中的 Result 进行操作,也可以使用 ? 操作符在返回 Option 的函数中对 Option 进行操作,但不能混合匹配。? 操作符不会自动将结果转换为选项,反之亦然。在这些情况下,可以使用 Result 上的 ok 方法或 Option 上的 ok_or 方法等方法显式地进行转换。

到目前为止,我们使用的所有 main函数都是 return ()。main 函数的特殊之处在于它是可执行程序的入口点和出口点,它的返回类型是有限制的,这样程序才能按照预期的方式运行。

幸运的是,main 函数也可以返回 Result<(), E>。我们将 main 函数的返回类型更改为 Result<(), Box<dyn Error>>,并在末尾添加返回值 Ok(())。这段代码现在可以编译了。

use std::error::Error;
use std::fs::File;

fn main() -> Result<(), Box<dyn Error>> {
    let greeting_file = File::open("hello.txt")?;

    Ok(())
}

Box<dyn Error> 类型是一个 trait 对象,表示“任何类型的错误”。使用 ? 允许在错误类型为 Box<dyn error> 的主函数中返回 Result 值,因为它允许提前返回任何 Err 值,即使在 main 函数体中添加更多返回其他错误的代码,这个签名仍然是正确的。

当 main 函数返回 Result<(), E> 时,如果 main 函数返回 Ok(()),可执行程序将以 0 的值退出;如果 main 函数返回 Err 值,可执行程序将以非 0 的值退出。这与用 C 编写的可执行程序的约定兼容。

main 函数可以返回任何实现 std::process::Termination trait 的类型,它包含一个返回 ExitCode 的函数报告。

panic or not panic,这是一个问题

本节将总结一些关于如何决定是否在库代码中 panic 的一般指导原则。

示例、原型代码和测试

当编写示例来说明某些概念时,使用 panic 可以使得示例变得清晰。

类似地,在决定如何处理错误之前,unwrap 和 expect 方法在原型制作时非常方便,它们会在代码中留下清晰的标记。

如果一个方法调用在测试中失败,希望整个测试都失败,用 panic 比较好。

拥有比编译器更多信息的情况

当代码确保 Result 将具有 Ok 值时,调用 unwrap 或 expect 也是合适的,但仍然有一个需要处理的 Err 变体。

示例:

    use std::net::IpAddr;

    let home: IpAddr = "127.0.0.1"
        .parse()
        .expect("Hardcoded IP address should be valid");

我们肯定希望以更健壮的方式处理结果。except 中处理了Result 为 Err 的情况。

为验证创建自定义类型

让我们进一步考虑使用 Rust 的类型系统来确保我们有一个有效的值,并看看如何创建一个用于验证的自定义类型。

完善之前的猜数游戏,引导用户进行有效的猜测,并在用户猜测超出范围的数字时与用户键入(例如字母)时具有不同的行为。

    loop {
        // --snip--

        let guess: i32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };

        if guess < 1 || guess > 100 {
            println!("The secret number will be between 1 and 100.");
            continue;
        }

        match guess.cmp(&secret_number) {
            // --snip--
    }

if 表达式检查我们的值是否超出了范围,之后继续进行 guess 和秘密数之间的比较。然而,这不是一个理想的解决方案:如果程序只对 1 到 100 之间的值进行操作是绝对关键的,并且它有许多具有此需求的函数,那么在每个函数中进行这样的检查将是乏味的(并且可能影响性能)。

相反,我们可以在专用模块中创建新类型,并将验证放入函数中以创建该类型的实例,而不是到处重复验证。这样,函数就可以安全地在其签名中使用新类型,并放心地使用它们接收到的值。我们定义 Guess 类型的一种方法,该方法只在新函数接收到 1 到 100 之间的值时创建实例。

pub struct Guess {
    value: i32,
}

impl Guess {
    pub fn new(value: i32) -> Guess {
        if value < 1 || value > 100 {
            panic!("Guess value must be between 1 and 100, got {value}.");
        }

        Guess { value }
    }

    pub fn value(&self) -> i32 {
        self.value
    }
}

首先,我们创建一个名为 guessing_game 的新模块。接下来,我们在该模块中定义了一个名为 Guess 的结构体,该结构体有一个 i32 类型、名为 value 的字段,这是存储数字的地方。

然后,我们在 Guess 上实现一个名为 new 的关联函数,该函数创建 Guess 值的实例。这个新函数被定义为有一个名为 value 的参数,类型为 i32,并返回 Guess。代码测试 value 以确保它在 1 到 100 之间。如果 value 没有通过这个测试,就会 panic。

接下来,我们实现一个名为 value 的方法,它借用 self,没有任何其他参数,并返回一个 i32。这种方法有时被称为 getter,因为它的目的是从字段中获取一些数据并返回这些数据。这个公共方法是必要的,因为 Guess 结构体的 value 字段是私有的。

如果一个函数有一个参数或者只返回 1 到 100 之间的数字,那么它就可以在它的签名中声明它接受或返回一个 Guess 而不是一个 i32,并且不需要在函数体中做任何额外的检查。

通过 from trait 返回自定义错误

这里将 io::Error 和 ParseIntError 通过 from trait 转换成枚举 MyError。

use std::{fs, io};
use std::fs::File;
use std::io::{read_to_string, Read};
use std::num::ParseIntError;

#[derive(Debug)]
pub enum MyError {
    Io(io::Error),
    ParseInt(ParseIntError),
    Other(String),
}

impl From<io::Error> for MyError {
    fn from(err: io::Error) -> Self {
        MyError::Io(err)
    }
}

impl From<ParseIntError> for MyError {
    fn from(err: ParseIntError) -> Self {
        MyError::ParseInt(err)
    }
}

fn read_username_from_file() -> Result<String, MyError> {
    let mut name = String::new();
    let file = File::open("username.txt")?.read_to_string(&mut name)?;
    let num: i32 = "55".parse()?;
    Ok(name)
}

fn main() {
    
}

错误处理指南

当您的代码可能以糟糕的状态结束时,建议让代码陷入 panic。坏状态包含:

  • 无效值、矛盾值或丢失值被传递给代码
  • 用户以错误的格式输入数据

然而,当失败在所难免时,返回 Result 比制造 panic 更合适。

总结

Rust 的错误处理特性旨在帮助编写更健壮的代码。

panic! 宏表示程序处于无法处理的状态,并将进程停止,而不是尝试使用无效或不正确的值继续。

枚举 Result 使用 Rust 的类型系统来指示操作可能失败的方式,代码可以从中恢复。

何时使用 panic:不可恢复的错误场景

  • 程序进入不可预期的 bad state
  • 安全问题
  • 代码不能继续执行
  • 违反函数契约或关键假设

何时使用 Result:可能恢复的错误场景

  • 提供恢复选项
  • 预期可能发生的错误
  • 希望调用者决定如何处理错误

推荐使用 panic 的情况:

  • 原型代码、示例、测试
  • 安全性关键的输入验证
  • 调用外部不可控代码时的异常状态

推荐使用 Result 的情况:

  • 处理可预期的错误
  • HTTP 请求失败
  • 解析错误
  • 用户输入验证

更多资料参见 Rust Book: Error Handling - To panic! or not to panic!

【Rust错误处理】Rust错误处理机制详解与应用实战 在 Rust 中,错误处理是一个核心特性,它通过 Result 和 Option 类型以及 panic! 机制来管理错误和异常情况。Rust 的错误处理强调显式性和安全性,避免了传统异常机制的隐式控制流问题。 Rust 主要有两种错误处理方式:可恢复错误和不可恢复错误。 阅读详情

相关推荐

使用 Java + PaddleOCR 实现表格识别,支持导出 HTML 和 Excel(附源码)

使用Java+PaddleOCR快速搭建表格识别系统,无需处理底层模型细节。系统支持表格结构识别和内容识别,可将图片转换为可编辑表格格式。文章提供了完整的实现流程,包括Maven依赖引入、模型下载(包含检测、识别、分类和表格结构模型)及参数配置说明。SmartJavaAI支持多种高性能模型选择,适用于不同应用场景,帮助开发者快速实现表格识别功能。

deng775747758的博客 1473

Rust中如何处理错误和异常?有哪些错误处理模式?

开发者可以根据需要选择不同的错误处理模式,从早期返回、错误链到自定义错误类型等,以确保代码的健壮性和可维护性。当函数遇到错误时,可以尽早返回错误结果,而不是继续执行后续的代码。当我们将一个函数的结果传递给另一个函数,并且希望将一种错误类型转换为另一种时,可以使用错误映射。通过定义自定义错误类型,我们可以更精确地描述和区分不同类型的错误,从而提供更清晰和有用的错误信息给调用者。有时,为了提供更具体和有意义的错误信息,我们可能需要定义自己的错误类型。方法来处理可能的除以零错误,如果发生错误则返回0作为备选值。

derickForster的博客 1967

手把手教你用Gazebo和VINS-MONO搞定VIO SLAM仿真(附Realsense D435i模型配置)

本文详细介绍了如何使用Gazebo和VINS-MONO构建VIO SLAM仿真环境,包括Realsense D435i模型的配置与集成。通过实战指南,帮助开发者快速搭建高保真仿真平台,优化VIO性能,并解决常见问题,适用于机器人感知与定位导航领域。

weixin_30682415的博客 158

Rust之错误处理

在Rust中,将错误分为两种,可恢复错误和不可恢复错误。所谓可恢复错误就是指类似于文件未找到这类错误,一般需要将它们报告给用户并再次尝试进行操作,而不可恢复错误往往就是Bug,需要停止程序的运行。

a_qwq_a的博客 1180

GD32F103RCT6/GD32F303RCT6(6.2)USART串口实战:从寄存器配置到DMA高效传输

本文详细介绍了GD32F103RCT6和GD32F303RCT6的USART串口通信实战,从寄存器配置到DMA高效传输的全过程。通过具体的代码示例和优化建议,帮助开发者快速掌握串口通信的关键技术,提升嵌入式开发效率。特别强调了DMA在高速数据传输中的优势和应用技巧。

weixin_33725239的博客 308

pandas,构造MultiIndex的四种方法:from_tuples、from_arrays、from_product、from_frame

1、from_tuples:通过 “元组对” 构造MultiIndex """ 一对元组,为一个索引 """ tuples = [(1, 'red'), (1, 'blue'), (2, 'red'), (2, 'blue')] pd.MultiIndex.from_tuples(tuples, names=('number', 'color')) 2、from_arrays:通过 “列表元素的组合” 构造MultiIndex """ 列中表的元素,按位置 对应组合,形成索引 """ arrays

jieru_liu的博客 5387

Rust 错误处理入门和进阶

Error Trait在标准库中定义。它基本上代表了错误值的期望 -中E类型的值。Error Trait针对许多错误实现,并为错误信息提供统一的 API。Error Trait有点需要,要求错误同时实现 Debug 和 Display。虽然实现起来可能很麻烦,但我们稍后会看到一些工具库来实现这一点。在标准库中,VarError(用于读取环境变量)和(用于将字符串切片解析为整数)是不同的错误。当我们与它们交互时,我们需要区分类型,因为它们具有不同的属性和不同的堆栈大小。

xuejianxinokok的专栏 1450

海康工业相机SDK开发实战:从环境搭建到实时图像采集(附避坑指南)

本文详细介绍了海康工业相机SDK在Windows平台上的开发实战流程,涵盖从环境搭建、运行时库路径配置到实时图像采集的全过程。重点解析了MVS SDK部署、设备连接、参数设置及图像处理等核心环节,并提供了实用的避坑指南和错误排查方法,帮助开发者构建稳定的机器视觉系统。

weixin_29248611的博客 845

【Rust 基础篇】Rust 错误处理详解

自定义错误类型是一种根据应用程序需求创建的特定错误类型。通过自定义错误类型,我们可以为不同的错误场景定义不同的错误类型,并在需要的地方使用这些类型。// 在发生错误的情况下返回自定义错误类型 Err(MyError :: SomeError) } fn main() {("操作成功") , Err(error) => match error {("遇到了 SomeError") , MyError :: AnotherError => println!

繁依Fanyi的博客 1824

HQChart实战教程64-自定义分时图标题栏

分时图标题栏显示的是当前十字光标所在位置的分钟信息,显示在分时图窗口顶部。一般会显示品种的名称,日期,时间,价格,均价 涨幅,成交量,金额等等,hqchart内置会显示这些信息。如果要额外显示其他的字段,就需要通过替换格式化标题输出函数来是现实。我们在hqchart实例创建完成以后,通过OnCreatedCallback回调函数替换自己的格式化输出函数。返回 { AryText:[ { Text:文字, Color:颜色},…入参 data={ Data: 当前十字光标所在位置的分钟线 }

小银 1056

NXOpenC#-通用NX对象操作Tag,Handle,TaggedObject介绍

NXOpenC#-通用NX对象操作Tag,Handle,TaggedObject介绍

阿飞2018 1184

Rust 学习笔记:关于错误处理的练习题

Rust 学习笔记:关于错误处理的练习题

ProgramNovice的博客 495

多物理场耦合仿真-主题032-电磁-流体耦合

电磁-流体耦合,即磁流体动力学(MHD, Magnetohydrodynamics),是研究导电流体在电磁场中运动规律的学科,涉及电磁场与流体力学的深度耦合。本主题系统阐述磁流体动力学的基本理论、控制方程和数值方法。首先介绍MHD的基本概念和物理基础,包括导电流体的性质、电磁场基本方程;然后详细推导MHD控制方程组,包括连续性方程、动量方程、能量方程和电磁场方程;接着讨论MHD流动的特征参数,如Hartmann数、磁雷诺数、相互作用参数等;最后通过六个典型工程案例展示MHD分析的实际应用,包括电磁泵、磁流体

2401_87715305的博客 423

学习笔记七——Rust错误处理

打开文件可能失败(标准库返回 io::Error)解析文件内容格式可能出错(比如不是合法数字)你想统一返回,那就需要定义自己的错误类型。Rust 不相信“侥幸不出错”,它要你在写代码时承认失败的可能性,并好好处理它。

pumpkin84514的博客 1135

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

[rust学习笔记]错误处理

Rust的错误分两种: 可恢复错误 不可恢复错误 rust提供了可恢复错误的类型Result< T,E >,与不可恢复错误时终止运行的panic!宏。 不可恢复错误与panic! 程序会在panic!宏执行时打印出一段错误提示信息,展开并清理当前的调用栈,然后退出程序,这种情况大部分都发生在某个错误被检测到,但程序员却不知道该如何处理的时候。 panic的栈展开与终止 panic发生时,程序默认会开始栈展开,就是会沿着函数调用的反向顺序清理函数中的数据,为了支持这种操作,我们需要在二进制中存

q435201823的博客 893

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

《Rust权威指南》学习笔记之第9章 错误处理

《Rust权威指南》学习笔记之第9章 错误处理不可恢复错误与panic!panic!中产生回溯信息可恢复错误与Result匹配不同错误失败时触发panic的快捷方式:unwrap和expect传播错误传播错误的快捷方式:?运算符 两大类错误: 可恢复错误 文件未找到等,报告给用户并再次尝试。Result<T, E> 不可恢复错误 bug,尝试访问超过数组结尾的位置等。panic! 不可恢复错误与panic! panic!宏执行时打印出一段错误提示信息,展开并清理当前的调用栈,然后退出程序。

yxqq378287007的博客 389

《Rust程序设计》学习笔记六:错误处理

使用格式说明符{:?},以获得该错误的Debug试图,这对用户不太友好,但包含额外的技术信息。上面的语句定义了公共类型std::io::Result<T>,它是Result<T, E>的别名,但将错误类型硬编码为std::io::Error。result.is_ok()和result.is_err(),这两个方法返回bool类型的值,用于表示result是已成功,还是已出错。result.expect(message),与.unwrap()行为相同,但允许你提供一条消息,在发生panic时打印出该消息。

look4liming的专栏 160

【学Python自动化】 8.1 Python 与 Rust 错误处理对比学习笔记

Python 自定义异常try:e } ")e } ")e } ")e } ")e } ")Rust 自定义错误} else {Ok(())

weixin_43219667的博客 457

Rust学习笔记:错误处理——panic!、Result、Option与_运算符

Rust 通过 panic! 处理不可恢复错误,用 Result<T, E> 和 Option<T> 处理可恢复错误,强制编译期检查。match、unwrap、expect 及 ? 运算符实现错误优雅传播,链式调用简洁高效。核心原则:优先使用 Result/Option,善用 ? 简化代码,避免滥用 panic!。

欢迎访问我的个人博客:https://www.lxpavilion.top/ 111

Rust学习笔记

​这是我观看杨旭老师的Rust教程的笔记,笔记中省略了一些细节部分,如有不理解的请大家观看杨旭老师的视频。

qq_59294755的博客 2189

Rust学习笔记_13——枚举

枚举通过enum关键字定义。每个枚举成员(也称为变体)可以是无值的,也可以包含值。

LuckyLay的博客 1106

Rust学习笔记(中)

笔记的内容主要参考与《Rust 程序设计语言》,一些也参考了《通过例子学 Rust》和《Rust语言圣经》。Rust学习笔记分为上中下,其它两个地址在我们可以使用泛型为像函数签名或结构体这样的项创建定义,这样它们就可以用于多种不同的具体数据类型。如下图,两个只在名称和签名中类型有所不同的函数,可以利用泛型优化它们。println!// 这里会报错largestprintln!println!选择T。

Fishermen_sail的博客 1351

Rust学习笔记-写个猜数字游戏

cargo new创建新项目构建项目cargo run运行项目导入io库let创建不可变变量let mut创建可变变量创建一个新的String实例,是一个新的空字符串表示参数的引用& guess引用不可变变量&mut guess引用可变变量Result是一种枚举类型,成员是Ok和ErrOk成员表示操作成功,内部包含成功时产生的值。Err成员则意味着操作失败,并且包含失败的前因后果。Result的实例拥有 expect方法。println!()中支持通过占位符{}来格式化字符串。

快乐的小小程序猿 457

rust基础

rust基础学习笔记

fengxiandada的博客 1932

rust学习链接

序号 链接 00 rust学习02安装 01 rust学习01附录 02 rust学习04变量 03 rust学习03猜游戏 04 rust学习06所有权上 05 rust学习06所有权上 06 rust学习05函数 07 rust学习08结构示例与09方法 08 c++增强c类接口安全性与rust学习07切片 09 rust学习11匹配与c++部分头. 10 rust学习10枚举 11 rust学习13用与14前部分 12 rust学习12包...

个人进步之路 557

Rust 学习笔记(基础篇)

rust 学习笔记

0xac001d09 3062
上一篇: Rust 学习笔记:关于 HashMap 的练习题
下一篇: Rust 学习笔记:关于错误处理的练习题
UestcXiye
博客等级 码龄8年 9028粉丝 1306原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值