rust多樣化錯(cuò)誤處理(從零學(xué)習(xí))
一、thiserror初體驗(yàn)
可以使用命令 cargo add thiserror
將它添加到自己的項(xiàng)目中,或者在 Cargo.toml
中添加如下的配置:
[dependencies] thiserror = "1.0"
thiserror
可以用于枚舉或者結(jié)構(gòu)體,例如,我們來(lái)看一個(gè)基本的例子:
use std::io; use log::error; use thiserror::Error; #[derive(Error,Debug)] pub enum DataStoreError { #[error("data store disconnected")] Disconnect(#[from] std::io::Error), #[error("the data for key `{0}` is not available")] Redaction(String), #[error("invalid header (expected {expected:?},found {found:?})")] InvalidHeader {expected:String,found:String}, #[error("unknown data store error")] Unknown } pub fn error(){ ///error println!("這是沒(méi)有參數(shù)的 Unknown {}",DataStoreError::Unknown); println!("這是結(jié)構(gòu)體參數(shù)的 InvalidHeader {}",DataStoreError::InvalidHeader { expected : String::from("expected"), found : String::from("found") }); println!("這是有index參數(shù)的 Redaction {}",DataStoreError::Redaction(String::from("Redaction"))); println!("這是有from參數(shù)的 Disconnect {}",DataStoreError::Disconnect(io::Error::from(io::ErrorKind::TimedOut))); }
這是沒(méi)有參數(shù)的 Unknown unknown data store error
這是結(jié)構(gòu)體參數(shù)的 InvalidHeader invalid header (expected "expected",found "found")
這是有index參數(shù)的 Redaction the data for key `Redaction` is not available
這是有from參數(shù)的 Disconnect data store disconnected
然后我們來(lái)仔細(xì)分析下各種用法
二、#[error]
如果使用 #[error(...)]
為結(jié)構(gòu)體或者枚舉生成自定義錯(cuò)誤消息,這將為它們實(shí)現(xiàn) Display
:
2.1 Enum
#[derive(Debug)] pub struct Limits{ lo : i16, hi : i16 } #[derive(Error,Debug)] pub enum MyError{ #[error("invalid rdo_lookahead_frames {0} (expected < {})",i8::MAX)] InvalidLookahead(u32), #[error("first letter must be lowercase but was {:?}",first_char(.0))] WrongCase(String), #[error("invalid index {idx},expected at least {} and at most {}",.limits.lo,.limits.hi)] OutOfBounds{idx:usize,limits:Limits} }
pub fn error(){ println!("這是 enum 的InvalidLookahead {}",MyError::InvalidLookahead(3333)); //自動(dòng)調(diào)用函數(shù)進(jìn)行比較 println!("這是 enum 的 WrongCase {}",MyError::WrongCase("kk".to_string())); println!("這是 enum 的 OutOfBounds {}",MyError::OutOfBounds{idx : 89,limits:Limits{ lo:12, hi:11 }}); }
這是 enum 的InvalidLookahead invalid rdo_lookahead_frames 3333 (expected < 127)
這是 enum 的 WrongCase first letter must be lowercase but was 'k'
這是 enum 的 OutOfBounds invalid index 89,expected at least 12 and at most 11
2.2 struct
#[derive(Error, Debug)] #[error("something failed, msg is: {msg}")] pub struct MyErrorStruct { msg: &'static str, }
println!("這是 struct 的msg {}",MyErrorStruct{msg:"失敗的msg"});
這是 struct 的msg something failed, msg is: 失敗的msg
2.3 其他結(jié)構(gòu)
其他結(jié)構(gòu)也是支持的,例如 tuple、空struct 等等
三、#[from]
可以使用 #[from]
注解為錯(cuò)誤類型實(shí)現(xiàn) From
,可以從其他錯(cuò)誤生成:
#[derive(Error, Debug)] #[error("some io error happened, {:?}", .source)] pub struct MyFromError { #[from] source: io::Error, }
println!("這是 struct 的 from 的 {}",MyFromError::from(io::Error::from(io::ErrorKind::TimedOut)));
這是 struct 的 from 的 some io error happened, Kind(TimedOut)
四、#[source]
可以使用 #[source]
屬性,或者將字段命名為 source
,可為自定義錯(cuò)誤實(shí)現(xiàn) source
方法,返回底層的錯(cuò)誤類型:
use std::error::Error; use std::io; use thiserror::Error; #[derive(Error, Debug)] pub enum MyError { #[error("some io error happened, {:?}", .source)] IO { source: io::Error }, } fn main() { let err = MyError::IO { source: io::Error::from(io::ErrorKind::TimedOut), }; println!("{:?}", err.source()); }
或者使用 #[source]
屬性標(biāo)記非 source
的字段,例如:這里是 err
字段:
use std::error::Error; use std::io; use thiserror::Error; #[derive(Error, Debug)] pub enum MyError { #[error("some io error happened, {:?}", .err)] IO { #[source] err: io::Error, }, } fn main() { let err = MyError::IO { err: io::Error::from(io::ErrorKind::TimedOut), }; println!("{:?}", err.source()); }
#[from]
和 #[source]
二選一即可,#[from]
也會(huì)為類型生成 .source()
方法,例如:
#![allow(unused)] #![feature(backtrace)] use std::backtrace; use std::error::Error as _; use std::io; use thiserror::Error; #[derive(Error, Debug)] #[error("some io error happened, {:?}", .source)] pub struct MyError { #[from] source: io::Error, backtrace: backtrace::Backtrace, } fn main() { let err = MyError::from(io::Error::from(io::ErrorKind::TimedOut)); println!("{:?}", err.source()); }
五、#[backtrace]
只要在我們的錯(cuò)誤結(jié)構(gòu)體里面放個(gè)類型為 std::backtrace::Backtrace
的字段,就會(huì)自動(dòng)實(shí)現(xiàn) backtrace()
方法,可以看 #[from]
。
另外,如果使用 #[backtrace]
標(biāo)記 source
(source
字段,或者 #[source]
,或者 #[from]
),那么 backtrace()
方法會(huì)轉(zhuǎn)發(fā)到 source
的 backtrace
。
六、#[error(transparent)]
可以通過(guò) #[error(transparent)]
讓 source
和 Display
直接使用底層的錯(cuò)誤,這對(duì)于那些想處理任何的類型來(lái)說(shuō)是很有用的:
use std::io; use log::error; use thiserror::Error; use anyhow::anyhow; use std::error::Error as _; #[derive(Error, #[derive(Error, Debug)] #[error(transparent)] pub struct MyErrorTrans { #[from] source: anyhow::Error, } #[derive(Error, Debug)] pub enum MyErrorTransEnum { #[error("file not found")] FileNotFound, #[error(transparent)] Other(#[from] anyhow::Error), // source and Display delegate to anyhow::Error }
//transparent let err = MyErrorTrans::from(anyhow!("Missing attribute: {}", "field1")); println!("{}", err); println!("{:?}", err); let err = MyErrorTransEnum::from(anyhow!("Missing attribute: {}", "field1")); println!("{}", err); println!("{:?}", err); Missing attribute: field1 MyErrorTrans { source: Missing attribute: field1 } Missing attribute: field1 Other(Missing attribute: field1)
以上就是rust多樣化錯(cuò)誤處理(從零學(xué)習(xí))的詳細(xì)內(nèi)容,更多關(guān)于rust多樣化錯(cuò)誤處理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Rust開(kāi)發(fā)WebAssembly在Html和Vue中的應(yīng)用小結(jié)(推薦)
這篇文章主要介紹了Rust開(kāi)發(fā)WebAssembly在Html和Vue中的應(yīng)用,本文將帶領(lǐng)大家在普通html上和vue手腳架上都來(lái)運(yùn)行wasm的流程,需要的朋友可以參考下2022-08-08Rust語(yǔ)言之結(jié)構(gòu)體和枚舉的用途與高級(jí)功能詳解
Rust 是一門注重安全性和性能的現(xiàn)代編程語(yǔ)言,其中結(jié)構(gòu)體和枚舉是其強(qiáng)大的數(shù)據(jù)類型之一,了解結(jié)構(gòu)體和枚舉的概念及其高級(jí)功能,將使你能夠更加靈活和高效地處理數(shù)據(jù),本文將深入探討 Rust 中的結(jié)構(gòu)體和枚舉,并介紹它們的用途和高級(jí)功能2023-10-10Rust編寫(xiě)自動(dòng)化測(cè)試實(shí)例權(quán)威指南
這篇文章主要為大家介紹了Rust編寫(xiě)自動(dòng)化測(cè)試實(shí)例權(quán)威指南詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12Rust中用enum實(shí)現(xiàn)多參數(shù)Hook機(jī)制完整代碼
在 Rust 中,如果想為enum實(shí)現(xiàn)一個(gè)帶多參數(shù)的 Hook 機(jī)制,可以結(jié)合模式匹配和枚舉來(lái)處理,這種方式可以擴(kuò)展到支持不同類型的輸入?yún)?shù)和邏輯處理,下面通過(guò)示例代碼介紹Rust中用enum實(shí)現(xiàn)多參數(shù)Hook機(jī)制,感興趣的朋友一起看看吧2024-12-12