rust多樣化錯誤處理(從零學(xué)習(xí))
一、thiserror初體驗
可以使用命令 cargo add thiserror 將它添加到自己的項目中,或者在 Cargo.toml 中添加如下的配置:
[dependencies] thiserror = "1.0"
thiserror 可以用于枚舉或者結(jié)構(gòu)體,例如,我們來看一個基本的例子:
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!("這是沒有參數(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)));
}這是沒有參數(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
然后我們來仔細分析下各種用法
二、#[error]
如果使用 #[error(...)] 為結(jié)構(gòu)體或者枚舉生成自定義錯誤消息,這將為它們實現(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));
//自動調(diào)用函數(shù)進行比較
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] 注解為錯誤類型實現(xiàn) From,可以從其他錯誤生成:
#[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,可為自定義錯誤實現(xiàn) source 方法,返回底層的錯誤類型:
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] 也會為類型生成 .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]
只要在我們的錯誤結(jié)構(gòu)體里面放個類型為 std::backtrace::Backtrace 的字段,就會自動實現(xiàn) backtrace() 方法,可以看 #[from]。
另外,如果使用 #[backtrace] 標(biāo)記 source(source 字段,或者 #[source],或者 #[from]),那么 backtrace() 方法會轉(zhuǎn)發(fā)到 source 的 backtrace。
六、#[error(transparent)]
可以通過 #[error(transparent)] 讓 source 和 Display 直接使用底層的錯誤,這對于那些想處理任何的類型來說是很有用的:
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多樣化錯誤處理(從零學(xué)習(xí))的詳細內(nèi)容,更多關(guān)于rust多樣化錯誤處理的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Rust開發(fā)WebAssembly在Html和Vue中的應(yīng)用小結(jié)(推薦)
這篇文章主要介紹了Rust開發(fā)WebAssembly在Html和Vue中的應(yīng)用,本文將帶領(lǐng)大家在普通html上和vue手腳架上都來運行wasm的流程,需要的朋友可以參考下2022-08-08
Rust語言之結(jié)構(gòu)體和枚舉的用途與高級功能詳解
Rust 是一門注重安全性和性能的現(xiàn)代編程語言,其中結(jié)構(gòu)體和枚舉是其強大的數(shù)據(jù)類型之一,了解結(jié)構(gòu)體和枚舉的概念及其高級功能,將使你能夠更加靈活和高效地處理數(shù)據(jù),本文將深入探討 Rust 中的結(jié)構(gòu)體和枚舉,并介紹它們的用途和高級功能2023-10-10
Rust中用enum實現(xiàn)多參數(shù)Hook機制完整代碼
在 Rust 中,如果想為enum實現(xiàn)一個帶多參數(shù)的 Hook 機制,可以結(jié)合模式匹配和枚舉來處理,這種方式可以擴展到支持不同類型的輸入?yún)?shù)和邏輯處理,下面通過示例代碼介紹Rust中用enum實現(xiàn)多參數(shù)Hook機制,感興趣的朋友一起看看吧2024-12-12

