安徽省水利厅j建设网站,宿州做企业网站,asp模版网站如何做优化,网站用户体验度返回值和错误处理
panic 深入剖析
主动调用
fn main() {panic!(crash and burn);
}backtrace 栈展开
panic 时的两种终止方式
当出现 panic! 时#xff0c;程序提供了两种方式来处理终止流程#xff1a;栈展开和直接终止
何时该使用 panic!
先来一点背景知…返回值和错误处理
panic 深入剖析
主动调用
fn main() {panic!(crash and burn);
}backtrace 栈展开
panic 时的两种终止方式
当出现 panic! 时程序提供了两种方式来处理终止流程栈展开和直接终止
何时该使用 panic!
先来一点背景知识在前面章节我们粗略讲过 ResultT, E 这个枚举类型它是用来表示函数的返回结果
enum ResultT, E {Ok(T),Err(E),
}当没有错误发生时函数返回一个用 Result 类型包裹的值 Ok(T)当错误时返回一个 Err(E)。对于 Result 返回我们有很多处理方法最简单粗暴的就是 unwrap 和 expect这两个函数非常类似我们以 unwrap 举例
use std::net::IpAddr;
let home: IpAddr 127.0.0.1.parse().unwrap();返回值和?
对返回的错误进行处理
use std::fs::File;
use std::io::ErrorKind;fn main() {let f File::open(hello.txt);let f match f {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),},other_error panic!(Problem opening the file: {:?}, other_error),},};
}上面代码在匹配出 error 后又对 error 进行了详细的匹配解析最终结果
如果是文件不存在错误 ErrorKind::NotFound就创建文件这里创建文件File::create 也是返回 Result因此继续用 match 对其结果进行处理创建成功将新的文件句柄赋值给 f如果失败则 panic 剩下的错误一律 panicexpect 跟 unwrap 很像也是遇到错误直接 panic, 但是会带上自定义的错误提示信息相当于重载了错误打印的函数
失败就 panic: unwrap 和 expect
在不需要处理错误的场景例如写原型、示例时我们不想使用 match 去匹配 ResultT, E 以获取其中的 T 值因为 match 的穷尽匹配特性你总要去处理下 Err 分支。那么有没有办法简化这个过程有答案就是 unwrap 和 expect。
use std::fs::File;fn main() {let f File::open(hello.txt).expect(Failed to open hello.txt);
}
如果调用这段代码时 hello.txt 文件不存在那么 unwrap 就将直接 panic
thread main panicked at called Result::unwrap() on an Err value: Os { code: 2, kind: NotFound, message: No such file or directory }, src/main.rs:4:37
note: run with RUST_BACKTRACE1 environment variable to display a backtraceexpect 跟 unwrap 很像也是遇到错误直接 panic, 但是会带上自定义的错误提示信息相当于重载了错误打印的函数
use std::fs::File;fn main() {let f File::open(hello.txt).expect(Failed to open hello.txt);
}报错如下
thread main panicked at Failed to open hello.txt: Os { code: 2, kind: NotFound, message: No such file or directory }, src/main.rs:4:37
note: run with RUST_BACKTRACE1 environment variable to display a backtrace
传播错误
程序几乎不太可能只有 A-B 形式的函数调用一个设计良好的程序一个功能涉及十几层的函数调用都有可能。而错误处理也往往不是哪里调用出错就在哪里处理实际应用中大概率会把错误层层上传然后交给调用链的上游函数进行处理错误传播将极为常见。
例如以下函数从文件中读取用户名然后将结果进行返回
use std::fs::File;
use std::io::{self, Read};fn read_username_from_file() - ResultString, io::Error {// 打开文件f是Result文件句柄,io::Errorlet f File::open(hello.txt);let mut f match f {// 打开文件成功将file句柄赋值给fOk(file) file,// 打开文件失败将错误返回(向上传播)Err(e) return Err(e),};// 创建动态字符串slet mut s String::new();// 从f文件句柄读取数据并写入s中match f.read_to_string(mut s) {// 读取成功返回Ok封装的字符串Ok(_) Ok(s),// 将错误向上传播Err(e) Err(e),}
}有几点值得注意
该函数返回一个 ResultString, io::Error 类型当读取用户名成功时返回 Ok(String)失败时返回 Err(io:Error)File::open 和 f.read_to_string 返回的 ResultT, E 中的 E 就是 io::Error 由此可见该函数将 io::Error 的错误往上进行传播该函数的调用者最终会对 ResultString,io::Error 进行再处理至于怎么处理就是调用者的事如果是错误它可以选择继续向上传播错误也可以直接 panic亦或将具体的错误原因包装后写入 socket 中呈现给终端用户。
。
传播界的大明星: ?
use std::fs::File;
use std::io;
use std::io::Read;fn read_username_from_file() - ResultString, io::Error {let mut f File::open(hello.txt)?;let mut s String::new();f.read_to_string(mut s)?;Ok(s)
}看到没这就是排面相比前面的 match 处理错误的函数代码直接减少了一半不止.
其实 ? 就是一个宏它的作用跟上面的 match 几乎一模一样
let mut f match f {// 打开文件成功将file句柄赋值给fOk(file) file,// 打开文件失败将错误返回(向上传播)Err(e) return Err(e),
};如果结果是 Ok(T)则把 T 赋值给 f如果结果是 Err(E)则返回该错误所以 ? 特别适合用来传播错误。
虽然 ? 和 match 功能一致但是事实上 ? 会更胜一筹。
想象一下一个设计良好的系统中肯定有自定义的错误特征错误之间很可能会存在上下级关系例如标准库中的 std::io::Error 和 std::error::Error前者是 IO 相关的错误结构体后者是一个最最通用的标准错误特征同时前者实现了后者因此 std::io::Error 可以转换为 std:error::Error。
明白了以上的错误转换? 的更胜一筹就很好理解了它可以自动进行类型提升转换
fn open_file() - ResultFile, Boxdyn std::error::Error {let mut f File::open(hello.txt)?;Ok(f)
}上面代码中 File::open 报错时返回的错误是 std::io::Error 类型但是 open_file 函数返回的错误类型是 std::error::Error 的特征对象可以看到一个错误类型通过 ? 返回后变成了另一个错误类型这就是 ? 的神奇之处。
根本原因是在于标准库中定义的 From 特征该特征有一个方法 from用于把一个类型转成另外一个类型? 可以自动调用该方法然后进行隐式类型转换。因此只要函数返回的错误 ReturnError 实现了 From 特征那么 ? 就会自动把 OtherError 转换为 ReturnError。
这种转换非常好用意味着你可以用一个大而全的 ReturnError 来覆盖所有错误类型只需要为各种子错误类型实现这种转换即可。
use std::fs::File;
use std::io;
use std::io::Read;fn read_username_from_file() - ResultString, io::Error {let mut s String::new();File::open(hello.txt)?.read_to_string(mut s)?;Ok(s)
}? 还能实现链式调用File::open 遇到错误就返回没有错误就将 Ok 中的值取出来用于下一个方法调用简直太精妙了.
use std::fs;
use std::io;fn read_username_from_file() - ResultString, io::Error {// read_to_string是定义在std::io中的方法因此需要在上面进行引用fs::read_to_string(hello.txt)
}从文件读取数据到字符串中是比较常见的操作因此 Rust 标准库为我们提供了 fs::read_to_string 函数该函数内部会打开一个文件、创建 String、读取文件内容最后写入字符串并返回因为该函数其实与本章讲的内容关系不大因此放在最后来讲其实只是我想震你们一下
? 用于 Option 的返回
? 不仅仅可以用于 Result 的传播还能用于 Option 的传播再来回忆下 Option 的定义
pub enum OptionT {Some(T),None
}Result 通过 ? 返回错误那么 Option 就通过 ? 返回 None
fn first(arr: [i32]) - Optioni32 {let v arr.get(0)?;Some(v)
}新手用 ? 常会犯的错误
初学者在用 ? 时老是会犯错例如写出这样的代码
fn first(arr: [i32]) - Optioni32 {arr.get(0)?
}这段代码无法通过编译切记? 操作符需要一个变量来承载正确的值这个函数只会返回 Some(i32) 或者 None只有错误值能直接返回正确的值不行所以如果数组中存在 0 号元素那么函数第二行使用 ? 后的返回类型为 i32 而不是 Some(i32)。因此 ? 只能用于以下形式
let v xxx()?;
xxx()?.yyy()?;带返回值的 main 函数
在了解了 ? 的使用限制后这段代码你很容易看出它无法编译
use std::fs::File;fn main() {let f File::open(hello.txt)?;
}运行后会报错:
$ cargo run...the ? operator can only be used in a function that returns Result or Option (or another type that implements FromResidual)-- src/main.rs:4:48|
3 | fn main() {| --------- this function should return Result or Option to accept ?
4 | let greeting_file File::open(hello.txt)?;| ^ cannot use the ? operator in a function that returns ()| help: the trait FromResidualResultInfallible, std::io::Error is not implemented for ()因为 ? 要求 ResultT, E 形式的返回值而 main 函数的返回是 ()因此无法满足那是不是就无解了呢
实际上 Rust 还支持另外一种形式的 main 函数
use std::error::Error;
use std::fs::File;fn main() - Result(), Boxdyn Error {let f File::open(hello.txt)?;Ok(())
}这样就能使用 ? 提前返回了同时我们又一次看到了Box 特征对象因为 std::error:Error 是 Rust 中抽象层次最高的错误其它标准库中的错误都实现了该特征因此我们可以用该特征对象代表一切错误就算 main 函数中调用任何标准库函数发生错误都可以通过 Boxdyn Error 这个特征对象进行返回。 文章转载自: http://www.morning.fqtdz.cn.gov.cn.fqtdz.cn http://www.morning.fbjnr.cn.gov.cn.fbjnr.cn http://www.morning.yqzyp.cn.gov.cn.yqzyp.cn http://www.morning.frfpx.cn.gov.cn.frfpx.cn http://www.morning.qcymf.cn.gov.cn.qcymf.cn http://www.morning.lqws.cn.gov.cn.lqws.cn http://www.morning.jrslj.cn.gov.cn.jrslj.cn http://www.morning.ydrn.cn.gov.cn.ydrn.cn http://www.morning.nzkc.cn.gov.cn.nzkc.cn http://www.morning.nd-test.com.gov.cn.nd-test.com http://www.morning.zrkp.cn.gov.cn.zrkp.cn http://www.morning.npxht.cn.gov.cn.npxht.cn http://www.morning.hgkbj.cn.gov.cn.hgkbj.cn http://www.morning.txhls.cn.gov.cn.txhls.cn http://www.morning.qygfb.cn.gov.cn.qygfb.cn http://www.morning.qzsmz.cn.gov.cn.qzsmz.cn http://www.morning.ggrzk.cn.gov.cn.ggrzk.cn http://www.morning.tnnfy.cn.gov.cn.tnnfy.cn http://www.morning.jxgyg.cn.gov.cn.jxgyg.cn http://www.morning.zlqyj.cn.gov.cn.zlqyj.cn http://www.morning.tgfsr.cn.gov.cn.tgfsr.cn http://www.morning.nnhrp.cn.gov.cn.nnhrp.cn http://www.morning.zmzdx.cn.gov.cn.zmzdx.cn http://www.morning.zbkdm.cn.gov.cn.zbkdm.cn http://www.morning.zypnt.cn.gov.cn.zypnt.cn http://www.morning.khtyz.cn.gov.cn.khtyz.cn http://www.morning.zfqr.cn.gov.cn.zfqr.cn http://www.morning.qwyms.cn.gov.cn.qwyms.cn http://www.morning.wmmtl.cn.gov.cn.wmmtl.cn http://www.morning.trtxt.cn.gov.cn.trtxt.cn http://www.morning.hxfrd.cn.gov.cn.hxfrd.cn http://www.morning.jnrry.cn.gov.cn.jnrry.cn http://www.morning.jghqc.cn.gov.cn.jghqc.cn http://www.morning.ldynr.cn.gov.cn.ldynr.cn http://www.morning.tqldj.cn.gov.cn.tqldj.cn http://www.morning.glpxx.cn.gov.cn.glpxx.cn http://www.morning.hqzmz.cn.gov.cn.hqzmz.cn http://www.morning.ntgsg.cn.gov.cn.ntgsg.cn http://www.morning.rkrcd.cn.gov.cn.rkrcd.cn http://www.morning.dskzr.cn.gov.cn.dskzr.cn http://www.morning.qwlml.cn.gov.cn.qwlml.cn http://www.morning.mkxxk.cn.gov.cn.mkxxk.cn http://www.morning.jnrry.cn.gov.cn.jnrry.cn http://www.morning.pyncx.cn.gov.cn.pyncx.cn http://www.morning.wkjzt.cn.gov.cn.wkjzt.cn http://www.morning.lhyhx.cn.gov.cn.lhyhx.cn http://www.morning.xmnlc.cn.gov.cn.xmnlc.cn http://www.morning.qichetc.com.gov.cn.qichetc.com http://www.morning.sgfpn.cn.gov.cn.sgfpn.cn http://www.morning.wjzzh.cn.gov.cn.wjzzh.cn http://www.morning.ydxx123.cn.gov.cn.ydxx123.cn http://www.morning.kryn.cn.gov.cn.kryn.cn http://www.morning.kmcfw.cn.gov.cn.kmcfw.cn http://www.morning.qxlgt.cn.gov.cn.qxlgt.cn http://www.morning.kehejia.com.gov.cn.kehejia.com http://www.morning.jhxdj.cn.gov.cn.jhxdj.cn http://www.morning.tbnn.cn.gov.cn.tbnn.cn http://www.morning.kklwz.cn.gov.cn.kklwz.cn http://www.morning.npcxk.cn.gov.cn.npcxk.cn http://www.morning.tgyqq.cn.gov.cn.tgyqq.cn http://www.morning.wdrxh.cn.gov.cn.wdrxh.cn http://www.morning.nkpml.cn.gov.cn.nkpml.cn http://www.morning.yyngs.cn.gov.cn.yyngs.cn http://www.morning.bqwrn.cn.gov.cn.bqwrn.cn http://www.morning.qjfkz.cn.gov.cn.qjfkz.cn http://www.morning.ymyhg.cn.gov.cn.ymyhg.cn http://www.morning.dxgt.cn.gov.cn.dxgt.cn http://www.morning.diuchai.com.gov.cn.diuchai.com http://www.morning.pqktp.cn.gov.cn.pqktp.cn http://www.morning.plqhb.cn.gov.cn.plqhb.cn http://www.morning.wwklf.cn.gov.cn.wwklf.cn http://www.morning.rykmz.cn.gov.cn.rykmz.cn http://www.morning.ptslx.cn.gov.cn.ptslx.cn http://www.morning.dblfl.cn.gov.cn.dblfl.cn http://www.morning.lfgql.cn.gov.cn.lfgql.cn http://www.morning.dnmzl.cn.gov.cn.dnmzl.cn http://www.morning.nmfxs.cn.gov.cn.nmfxs.cn http://www.morning.lsmnn.cn.gov.cn.lsmnn.cn http://www.morning.lwcqh.cn.gov.cn.lwcqh.cn http://www.morning.wsxxq.cn.gov.cn.wsxxq.cn