贵州服务器推荐云空间Rust编程语言-错误处理

华为企业云服务器配置 名词解释 panic:恐慌 错误大致分成两类 rust大部分错误在编译的时候就能够提示研发,让研发完成修复。但还是存在一些问题,编译阶段是不知道的,大致···

华为企业云服务器配置

名词解释

panic:恐慌

错误大致分成两类

rust大部分错误在编译的时候就能够提示研发,让研发完成修复。但还是存在一些问题,编译阶段是不知道的,大致可以分为两类:

可恢复错误:例如文件未找到,我们可以提示用户进行重试,不用中断程序不可恢复错误:例如访问的索引超出范围这类BUG

针对这两种错误的处理方式:

可恢复错误:Rust提供了Result来封装信息,程序不会中断执行不可恢复错误:Rust提供了panic! 宏来处理不可恢复错误,程序会立即中断执行

如何通过painic!宏来处理不可恢复错误

当不可恢复错误发生的时候rust会自动执行panic! ,执行panic! 宏会发生:

你的程序会打印一个错误信息展开(unwind)、清理调用栈(stack)退出程序

对应 panic 时的栈展开或终止

当出现 panic 时,程序默认会开始展开unwinding),这意味着 Rust 会回溯栈并清理它遇到的每一个函数的数据,不过这个回溯并清理的过程有很多工作(工作量大)。另一种选择是直接终止abort),不清理数据就退出程序,数据由操作系统后续回收。

如果想让项目二进制文件越小越好,就使用终止这种方式。只需要在cargo.toml文件中添加如下内容就可以了:

在release模式中panic时直接终止[profile.release]panic=abort

下面是一个panic示例:

fn main() {panic!("crash and burn"); } $ cargo run Compilingpanicv0.1.0(file:///projects/panic)Finished dev [unoptimized + debuginfo] target(s) in0.25s Running`target/debug/panic`threadmainpanicked atcrash and burn, src/main.rs:2:5note: run with`RUST_BACKTRACE=1`environment variable to display a backtrace

最后两行包含panic!调用造成的错误信息。第一行显示了 panic 提供的信息并指明了源码中 panic 出现的位置:src/main.rs:2:5表明这是src/main.rs文件的第二行第五个字符。

有时候出现 panic 的地方不是我们自己写的代码,而是调用库导致的。为了确定我们自己调用库代码的位置就需要使用backtrace。

使用panic!的 backtrace

fnmain() {letv =vec![1,2,3]; v[99]; }

我们在运行main.rs文件的时候加上 RUST_BACKTRACE=1 就可以了:

$setRUST_BACKTRACE=1&& cargo runthreadmainpanickedatindex out of bounds: the len is 3 but the index is 99, src/main.rs:4:5stack backtrace:0: rust_begin_unwindat/rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/panicking.rs:584:51: core::panicking::panic_fmtat/rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/panicking.rs:142:142: core::panicking::panic_bounds_checkat/rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/panicking.rs:84:53: ascore::slice::index::SliceIndex<[T]>>::indexat/rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/slice/index.rs:242:104: core::slice::index::Indexfor[T]>::indexat/rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/slice/index.rs:18:95: ascore::ops::index::Index>::indexat/rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/alloc/src/vec/mod.rs:2591:96: panic::mainat./src/main.rs:4:57: core::ops::function::FnOnce::call_onceat/rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ops/function.rs:248:5note:Somedetailsareomitted, runwith`RUST_BACKTRACE=full`fora verbose backtrace.

用Result处理可恢复的错误

下面代码是Result的定义:

T:操作成功情况下,OK变体里返回的数据的类型E:操作失败情况下,Err变体里返回的错误类型enumResult {Ok(T),Err(E), }

示例:

微软云服务器怎么搭建

usestd::fs::File;fnmain() {letgreeting_file_result = File::open("hello.txt");letgreeting_file =matchgreeting_file_result {Ok(file) => file,Err(error) =>panic!("Problem opening the file: {:?}", error), }; }

File::open返回的就是一个Result。

匹配不同的错误

usestd::fs::File;usestd::io::ErrorKind;fnmain() {letgreeting_file_result = File::open("hello.txt");letgreeting_file =matchgreeting_file_result {Ok(file) => file,Err(error) =>matcherror.kind() { ErrorKind::NotFound =>matchFile::create("hello.txt") {Ok(fc) => fc,Err(e) =>panic!("Problem creating the file: {:?}", e), }, other_error => {panic!("Problem opening the file: {:?}", other_error); } }, }; }File::open返回的Err成员中的值类型io::Error,它是一个标准库中提供的结构体。这个结构体有一个返回io::ErrorKind值的kind方法可供调用。io::ErrorKind 中有一个NotFound,如果未找到文件,我们就创建一个文件使用 File::create这个方法也返回一个io:Error,所以我们在用match解析结果,添加成功返回文件,失败就终止程序

失败时 panic 的简写:unwrap和expect

阿里云加密视频服务器

上面的例子中我们用到了很多match,但代码很冗余。Result类型定义了很多辅助方法来处理各种情况。其中之一叫做unwrap。

如果Result值是成员Okunwrap会返回Ok中的值。如果Result是成员Errunwrap会为我们调用panic!另一个类似于unwrap的方法它还允许我们选择panic!的错误信息:expectusestd::fs::File;fnmain() {letgreeting_file = File::open("hello.txt").unwrap();letgreeting_file = File::open("hello.txt") .expect("hello.txt should be included in this project"); }

传播错误

将错误包裹起来,作为函数返回值,由调用者决定如何处理错误,这种处理方式就是传播错误。

usestd::fs::File;usestd::io::{self, Read};// 返回Result类型,正确时返回文件内容,string类型,错误时返回Errorfnread_username_from_file() ->Result<String, io::Error> {// 读取文件正好也是返回的Result类型letusername_file_result = File::open("hello.txt");// 读取文件失败直接reture一个Err,函数就结束了,返回了一个Err给调用者// 读取成功的话就是一个File对象letmutusername_file =matchusername_file_result {Ok(file) => file,Err(e) =>returnErr(e), };letmutusername =String::new();// 上面文件读取成功,我们需要将File文件数据转成string// read_to_string 也是返回Result结果// 因为是最后一个表达式,所以Err没有显示调用return// 如果读取成功要返回Result的OK类型,所以用Ok包裹了username// 上面读取文件成功不会函数返回,所以未使用Ok包裹matchusername_file.read_to_string(&mutusername) {Ok(_) =>Ok(username),Err(e) =>Err(e), } }fnmain() {leta = read_username_from_file();matcha {Ok(txt) =>println!("{txt}"),Err(e) =>panic!("{e}"), } }

传播错误的简写:?运算符

将上面代码使用 ? 运算符简化:

usestd::fs::File;usestd::io::{self, Read};fnread_username_from_file() ->Result<String, io::Error> {// Result后面的 ?作用和上面 match一样// Result是Ok,就返回Ok的内容// Result是Err,就直接reture Errletmutusername_file = File::open("hello.txt")?;letmutusername =String::new(); username_file.read_to_string(&mutusername)?;Ok(username) }fnmain() {letcontent = read_username_from_file().unwrap();println!("{content}") }

?与from函数

因为我们调用的方法不都是返回的io::Error错误,只要这个错误实现了from函数,? 就会自动调用 ?函数将错误信息转换成我们函数要返回的错误。

也就是 源错误 实现了from 函数,将源错误转换成目标错误。如果没实现,问号会报错。

链式调用

usestd::fs::File;usestd::io::{self, Read};fnread_username_from_file() ->Result<String, io::Error> {letmutusername =String::new(); File::open("hello.txt")?.read_to_string(&mutusername)?;Ok(username) }fnmain() {letcontent = read_username_from_file().unwrap();println!("{content}") }

和上面调用一样。

?支持的类型

ResultOption

当应用在 Result 类型的值上时,它可以传播错误。 如果值是 Err(e),那么它实际上将从此操作符所在的函数体或闭包中返回 Err(From::from(e))。 如果应用到 Ok(x),那么它将解包此值以求得 x。

![allow(unused)]fnmain() {usestd::num::ParseIntError;fntry_to_parse() ->Result<i32, ParseIntError> {letx:i32="123".parse()?;// x = 123lety:i32="24a".parse()?;// 立即返回一个 Err()Ok(x + y)// 不会执行到这里}letres = try_to_parse();println!("{:?}", res);assert!(res.is_err()) }

当应用到 Option 类型的值时,它向调用者传播错误 None。 如果它应用的值是 None,那么它将返回 None。 如果应用的值是 Some(x),那么它将解包此值以求得 x。

![allow(unused)]fnmain() {fntry_option_some() ->Option<u8> {letval =Some(1)?;Some(val) }assert_eq!(try_option_some(),Some(1));fntry_option_none() ->Option<u8> {letval =None?;Some(val) }assert_eq!(try_option_none(),None); }

云服务器上传文件ftp

您好:云优数据云计算 www.yunyoushuju.cn 2核2G6M最低19.9元/月 欢迎开机

发表评论

评论列表
未查询到任何数据!