尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

std1.97.1——error模块总览

std1.97.1——error模块总览 目录0. 引言1. 错误处理1.1 Panic接口1.2 将错误转换成panic1.3 expect消息风格2. Error trait(重点)2.1 错误来源2.2 source2.3.0 impl dyn Trait(标准库里提了但是没有地方讲过)2.3.1 impl dyn Error/impl dyn Error Send/impl dyn Error Send Sync参考0. 引言重点只有Error trait其他都是归属于别的模块属于交叉部分用于处理错误的接口。1. 错误处理Rust提供了两套互补的系统用于构造/表示、报告、传播、响应和丢弃错误。第一套是panic运行时和接口——最常用于表示程序中检测到的bug。第二套是Result、Error trait和用户自定义类型——用于表示程序中可预见的运行时失败模式。1.1 Panic接口以下是panic系统的主要接口以及其覆盖的职责panic!和panic_any(构造、自动传播)set_hook、take_hook和PanicHookInfo(报告)#[panic_handler]和PanicInfo(no_std下的报告)catch_unwind和resume_unwind(丢弃传播); 以下是错误系统的主要接口及其覆盖的职责Result(传播响应)Error trait(报告)用户自定义类型(构造/表示)match和downcast(响应)问号运算符?(传播)部分稳定的Try trait(传播构造)Termination(报告)1.2 将错误转换成panicpanic系统和错误系统并非完全独立。某个错误在API层面是可预见的运行时失败但对调用者而言可能代表一个bug。针对这类情况标准库提供了以Error作为来源构造panic的APIResult::unwrapResult::expect这两个函数功能等价当Result为Ok时返回内部值为Err时panic并将内部错误作为来源打印。唯一的区别是expect允许你提供一条panic错误信息与来源一同打印unwrap使用默认信息仅说明你unwrap了一个Err。两者中通常更推荐expect因为它的msg参数让你能表达意图和假设使追踪panic来源更容易。unwrap则适用于能轻松证明代码不会panic的场景或早期原型开发阶段。1.3 expect消息风格在编写expect消息时有两种常见风格用消息向遇到panic的用户呈现信息或用消息向调试panic的开发者呈现信息。前者用expect描述已发生的、被视为bug的错误// 读取环境变量不存在则panicletpathstd::env::var(IMPORTANT_PATH).unwrap()将上面的例子用expect改写msg中描述错误信息letpathstd::env::var(IMPORTANT_PATH).expect(env variable IMPORTANT_PATH is not set);将msg描述错误信息改为msg描述前置条件描述预期Result为Ok的理由letpathstd::env::var(IMPORAT_PATH).expect(env variable IMPORTANT_PATH should be set by wrapper_script.sh);expect作为错误信息与标准panic hook的默认输出配合不佳往往会重复被unwrap的来源错误已经传达的信息thread main panicked at src/main.rs:4:6 env variable IMPORTANT_PATH is not set: NotPresentexpect作为前置条件则聚焦于源码可读性在panic专门用于表示bug的场景下更容易理解出了什么问题。此外通过以应该发生什么来框定expect我们引入了独立于来源错误的新信息thread main panicked at src/main.rs:4:6: env variable IMPORTANT_PATH should be set by wrapper_script.sh: NotPresent2. Error trait(重点)pubtraitError:DebugDisplay{fnsource(self)-Option(dynErrorstatic){...}}Error是一个trait表示对错误值的基本期望即ResultT, E中E类型的值。实现Error之前必须先实现Debug和Display trait(参考std::fmt模块总览)。错误消息通常是简洁的小写句子不带结尾标点fnmain(){leterrNaN.parse::u32().unwrap_err();println!({},err.to_string());}2.1 错误来源错误可以提供原因信息。Error::source()通常在错误跨抽象边界时使用。如果某个模块必须报告一个由更低层模块的错误导致的错误它可以通过Error::source()来允许访问那个底层错误。这使得高层模块既能提供自己的错误信息同时也能在调试时揭示部分实现细节。在包装了底层错误的错误类型中底层错误应该要么通过外层错误的Error::source()返回要么通过外层错误的Display实现来渲染但不应两者兼有。2.2 source方法签名fnsource(self)-Option(dynErrorstatic)返回此错误的底层来源(如果有)。底层来源必须是实现了Error trait的类型且为’static的即不持有任何非’static的引用。usestd::error::Error;usestd::fmt;#[derive(Debug)]structSuperError{source:SuperErrorSideKick,}implfmt::DisplayforSuperError{fnfmt(self,f:mutfmt::Formatter_)-fmt::Result{write!(f,SuperError is here!)}}implErrorforSuperError{fnsource(self)-Option(dynErrorstatic){Some(self.source)}}#[derive(Debug)]structSuperErrorSideKick;implfmt::DisplayforSuperErrorSideKick{fnfmt(self,f:mutfmt::Formatter_)-fmt::Result{write!(f,SuperErrorSideKick is here!)}}implErrorforSuperErrorSideKick{}fnget_super_error()-Result(),SuperError{Err(SuperError{source:SuperErrorSideKick})}fnmain(){matchget_super_error(){Err(e){println!(Error: {e});println!(Caused by: {},e.source().unwrap());}_println!(No error),}}2.3.0 impl dyn Trait(标准库里提了但是没有地方讲过)dyn Trait本身是一个类型impl dyn Trait就是为这个类型定义固有方法。这些方法只附着在trait object上具体类型和trait本身都不受影响。标准库用这个语法为dyn Error和dyn Any提供了向下转型能力(is、downcast_ref、downcast_mut)让你在类型被擦除后能判断或恢复具体类型。2.3.1 impl dyn Error/impl dyn Error Send/impl dyn Error Send Sync三者是不同的类型各有实现。dyn Error Send和dyn Error Send Sync只是转发到dyn Error上定义的方法存在的原因是不同约束的trait object是不同类型。泛型参数T的约束是必须实现Error trait且为’static的。方法作用is::T()判断内部值是否为错误类型Tdowncast_ref::T()尝试获取错误类型T的引用返回OptionTdowncast_mut::T()尝试获取错误类型T的可变引用返回Optionmut Tdowncast::T()尝试将Boxdyn Error/Boxdyn Error Send/BoxError Send Sync转为BoxT返回ResultBoxT, Boxdyn Error/dyn Error Send/dyn Error Send Sync参考1、Rust std::error
返回列表