华为企业云服务器配置 名词解释 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:用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值是成员Ok,unwrap会返回Ok中的值。如果Result是成员Err,unwrap会为我们调用panic!。另一个类似于unwrap的方法它还允许我们选择panic!的错误信息:expect。usestd::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

发表评论
最近发表
标签列表