在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Rust中的錯(cuò)誤處理方法

jf_wN0SrCdH ? 來(lái)源:Rust語(yǔ)言中文社區(qū) ? 2023-02-20 09:37 ? 次閱讀

Rust中的錯(cuò)誤處理

Result枚舉

Rust 中沒有提供類似于 JavaC++ 中的 Exception 機(jī)制,而是使用Result枚舉的方式來(lái)實(shí)現(xiàn):


	

pub enum Result { /// Contains the success value Ok(T), /// Contains the error value Err(E), }

在使用時(shí):

  • 如果無(wú)錯(cuò)誤則使用Ok(T)返回;

  • 如果存在錯(cuò)誤,則使用Err(E)包裝錯(cuò)誤類型返回;

例如:

examples/0_result.rs


	

#[derive(Debug)] pub enum MyError { Internal(String), InvalidId(String), } fn add(num: i64) -> Result<i64, MyError> { if num < 0 { Err(MyError::InvalidId(String::from("Invalid num!"))) } else { Ok(num + 100000) } } fn main() -> Result<(), MyError> { // fetch_id(-1)?; let res = add(1)?; println!("{}", res); Ok(()) }

上面的代碼首先通過(guò) MyError 枚舉定義了多個(gè)可能會(huì)出現(xiàn)的錯(cuò)誤;

隨后,在add函數(shù)中:

  • 當(dāng) num 小于 0 時(shí)返回錯(cuò)誤;

  • 否則給 num 增加 100000 并返回;

在上面的let res = add(1)?;中使用了?操作符,他相當(dāng)于是一個(gè)語(yǔ)法糖:

  • 如果被調(diào)函數(shù)正常返回則調(diào)用unwrap獲取其值;

  • 反之,則將被調(diào)函數(shù)的錯(cuò)誤直接向上返回(相當(dāng)于直接 return Err);

即上面的語(yǔ)法糖相當(dāng)于:


	

let res = match add() { Ok(id) => id, Err(err) => { return Err(err); } };

錯(cuò)誤類型轉(zhuǎn)換

上面簡(jiǎn)單展示了 Rust 中錯(cuò)誤的使用;

由于 Rust 是強(qiáng)類型的語(yǔ)言,因此如果在一個(gè)函數(shù)中使用?返回了多個(gè)錯(cuò)誤,并且他們的類型是不同的,還需要對(duì)返回的錯(cuò)誤類型進(jìn)行轉(zhuǎn)換,轉(zhuǎn)為相同的類型!

例如下面的例子:


	

#[derive(Debug)] pub enum MyError { ReadError(String), ParseError(String), } fn read_file() -> Result<i64, MyError> { // Error: Could not get compiled! let content = fs::read_to_string("/tmp/id")?; let id = content.parse::<i64>()?; } fn main() -> Result<(), MyError> { let id = read_file()?; println!("id: {}", id); Ok(()) }

上面的例子無(wú)法編譯通過(guò),原因在于:read_to_stringparse返回的是不同類型的錯(cuò)誤!

因此,如果要能返回,我們需要對(duì)每一個(gè)錯(cuò)誤進(jìn)行轉(zhuǎn)換,轉(zhuǎn)為我們所定義的 Error 類型;

例如:

examples/1_error_convert.rs


	

fn read_file() -> Result<i64, MyError> { // Error: Could not get compiled! // let content = fs::read_to_string("/tmp/id")?; // let id = content.parse::()?; // Method 1: Handling error explicitly! let content = match std::read_to_string("/tmp/id") { Ok(content) => content, Err(err) => { return Err(MyError::ReadError(format!("read /tmp/id failed: {}", err))); } }; let content = content.trim(); println!("read content: {}", content); // Method 2: Use map_err to transform error type let id = content .parse::<i64>() .map_err(|err| MyError::ParseError(format!("parse error: {}", err)))?; Ok(id) }

上面展示了兩種不同的轉(zhuǎn)換 Error 的方法:

方法一通過(guò) match 匹配手動(dòng)的對(duì)read_to_string函數(shù)的返回值進(jìn)行處理,如果發(fā)生了 Error,則將錯(cuò)誤轉(zhuǎn)為我們指定類型的錯(cuò)誤;

方法二通過(guò)map_err的方式,如果返回的是錯(cuò)誤,則將其轉(zhuǎn)為我們指定的類型,這時(shí)就可以使用?返回了;

相比之下,使用 map_err 的方式,代碼會(huì)清爽很多!

From Trait

上面處理錯(cuò)誤的方法,每次都要對(duì)錯(cuò)誤的類型進(jìn)行轉(zhuǎn)換,比較麻煩;

Rust 中提供了 From Trait,在進(jìn)行類型匹配時(shí),如果提供了從一個(gè)類型轉(zhuǎn)換為另一個(gè)類型的方法(實(shí)現(xiàn)了某個(gè)類型的 From Trait),則在編譯階段,編譯器會(huì)調(diào)用響應(yīng)的函數(shù),直接將其轉(zhuǎn)為相應(yīng)的類型!

例如:

examples/2_from_trait.rs


	

#[derive(Debug)] pub enum MyError { ReadError(String), ParseError(String), } impl From for MyError { fn from(source: std::Error) -> Self { MyError::ReadError(source.to_string()) } } impl From for MyError { fn from(source: std::ParseIntError) -> Self { MyError::ParseError(source.to_string()) } } fn read_file() -> Result<i64, MyError> { let _content = fs::read_to_string("/tmp/id")?; let content = _content.trim(); let id = content.parse::<i64>()?; Ok(id) } fn main() -> Result<(), MyError> { let id = read_file()?; println!("id: {}", id); Ok(()) }

在上面的代碼中,我們?yōu)?MyError 類型的錯(cuò)誤分別實(shí)現(xiàn)了轉(zhuǎn)換為std::Errorstd::ParseIntError類型的 From Trait;

因此,在 read_file 函數(shù)中就可以直接使用?向上返回錯(cuò)誤了!

但是上面的方法需要為每個(gè)錯(cuò)誤實(shí)現(xiàn) From Trait 還是有些麻煩,因此出現(xiàn)了thiserror以及anyhow庫(kù)來(lái)解決這些問(wèn)題;

其他第三方庫(kù)

thiserror

上面提到了我們可以為每個(gè)錯(cuò)誤實(shí)現(xiàn) From Trait 來(lái)直接轉(zhuǎn)換錯(cuò)誤類型,thiserror庫(kù)就是使用這個(gè)邏輯;

我們可以使用 thiserror 庫(kù)提供的宏來(lái)幫助我們生成到對(duì)應(yīng)類型的 Trait;

例如:

examples/3_thiserror.rs


	

#[derive(thiserror::Error, Debug)] pub enum MyError { #[error("io error.")] IoError(#[from] std::Error), #[error("parse error.")] ParseError(#[from] std::ParseIntError), } fn read_file() -> Result<i64, MyError> { // Could get compiled! let content = fs::read_to_string("/tmp/id")?; let id = content.parse::<i64>()?; Ok(id) } fn main() -> Result<(), MyError> { let id = read_file()?; println!("id: {}", id); Ok(()) }

我們只需要對(duì)我們定義的類型進(jìn)行宏標(biāo)注,在編譯時(shí)這些宏會(huì)自動(dòng)展開并實(shí)現(xiàn)對(duì)應(yīng)的 Trait;

展開后的代碼如下:


	

#![feature(prelude_import)] #[prelude_import] use std::*; #[macro_use] extern crate std; use std::fs; pub enum MyError { #[error("io error.")] IoError(#[from] std::Error), #[error("parse error.")] ParseError(#[from] std::ParseIntError), } #[allow(unused_qualifications)] impl std::Error for MyError { fn source(&self) -> std::Option<&(dyn std::Error + 'static)> { use thiserror::AsDynError; #[allow(deprecated)] match self { MyError::IoError { 0: source, .. } => std::Option::Some(source.as_dyn_error()), MyError::ParseError { 0: source, .. } => { std::Option::Some(source.as_dyn_error()) } } } } #[allow(unused_qualifications)] impl std::Display for MyError { fn fmt(&self, __formatter: &mut std::Formatter) -> std::Result { #[allow(unused_variables, deprecated, clippy::used_underscore_binding)] match self { MyError::IoError(_0) => { let result = __formatter.write_fmt(::new_v1(&["io error."], &[])); result } MyError::ParseError(_0) => { let result = __formatter.write_fmt(::new_v1(&["parse error."], &[])); result } } } } #[allow(unused_qualifications)] impl std::From for MyError { #[allow(deprecated)] fn from(source: std::Error) -> Self { MyError::IoError { 0: source } } } #[allow(unused_qualifications)] impl std::From for MyError { #[allow(deprecated)] fn from(source: std::ParseIntError) -> Self { MyError::ParseError { 0: source } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::Debug for MyError { fn fmt(&self, f: &mut ::Formatter) -> ::Result { match (&*self,) { (&MyError::IoError(ref __self_0),) => { ::debug_tuple_field1_finish(f, "IoError", &&*__self_0) } (&MyError::ParseError(ref __self_0),) => { ::debug_tuple_field1_finish(f, "ParseError", &&*__self_0) } } } } fn read_file() -> Result<i64, MyError> { let content = fs::read_to_string("/tmp/id")?; let id = content.parse::<i64>()?; Ok(id) } #[allow(dead_code)] fn main() -> Result<(), MyError> { let id = read_file()?; { ::new_v1( &["id: ", " "], &[::new_display(&id)], )); }; Ok(()) } #[rustc_main] pub fn main() -> () { extern crate test; test::test_main_static(&[]) }

可以看到實(shí)際上就是為 MyError 實(shí)現(xiàn)了對(duì)應(yīng)錯(cuò)誤類型的 From Trait;

thiserror 庫(kù)的這種實(shí)現(xiàn)方式,還需要為類型指定要轉(zhuǎn)換的錯(cuò)誤類型;

而下面看到的 anyhow 庫(kù),可以將錯(cuò)誤類型統(tǒng)一為同一種形式;

anyhow

如果你對(duì) Go 中的錯(cuò)誤類型不陌生,那么你就可以直接上手 anyhow 了!

來(lái)看下面的例子:

examples/4_anyhow.rs


	

use anyhow::Result; use std::fs; fn read_file() -> Result<i64> { // Could get compiled! let content = fs::read_to_string("/tmp/id")?; let id = content.parse::<i64>()?; Ok(id) } fn main() -> Result<()> { let id = read_file()?; println!("id: {}", id); Ok(()) }

注意到,上面的 Result 類型為anyhow::Result,而非標(biāo)準(zhǔn)庫(kù)中的 Result 類型!

anyhowResult實(shí)現(xiàn)了ContextTrait:


	

impl Context for Result where E: ext::StdError + Send + Sync + 'static, { fn context(self, context: C) -> Result where C: Display + Send + Sync + 'static, { // Not using map_err to save 2 useless frames off the captured backtrace // in ext_context. match self { Ok(ok) => Ok(ok), Err(error) => Err(error.ext_context(context)), } } fn with_context(self, context: F) -> Result where C: Display + Send + Sync + 'static, F: FnOnce() -> C, { match self { Ok(ok) => Ok(ok), Err(error) => Err(error.ext_context(context())), } } }

Context中提供了context函數(shù),并且將原來(lái)的Result轉(zhuǎn)成了Result

因此,最終將錯(cuò)誤類型統(tǒng)一為了anyhow::Error類型;

附錄

源代碼:

  • https://github.com/JasonkayZK/rust-learn/tree/error

審核編輯:湯梓紅


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • JAVA
    +關(guān)注

    關(guān)注

    20

    文章

    2984

    瀏覽量

    106932
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4371

    瀏覽量

    64223
  • C++
    C++
    +關(guān)注

    關(guān)注

    22

    文章

    2117

    瀏覽量

    74789
  • 枚舉
    +關(guān)注

    關(guān)注

    0

    文章

    16

    瀏覽量

    4690
  • Rust
    +關(guān)注

    關(guān)注

    1

    文章

    233

    瀏覽量

    6965

原文標(biāo)題:[Rust筆記] Rust中的錯(cuò)誤處理

文章出處:【微信號(hào):Rust語(yǔ)言中文社區(qū),微信公眾號(hào):Rust語(yǔ)言中文社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    嵌入式編程錯(cuò)誤處理機(jī)制設(shè)計(jì)

    本文主要總結(jié)嵌入式系統(tǒng)C語(yǔ)言編程,主要的錯(cuò)誤處理方式。文中涉及的代碼運(yùn)行環(huán)境如下。
    發(fā)表于 04-28 09:59 ?939次閱讀
    嵌入式編程<b class='flag-5'>錯(cuò)誤處理</b>機(jī)制設(shè)計(jì)

    嵌入式系統(tǒng)C語(yǔ)言編程主要的錯(cuò)誤處理方式

    本文主要總結(jié)嵌入式系統(tǒng)C語(yǔ)言編程,主要的錯(cuò)誤處理方式。
    發(fā)表于 07-24 16:40 ?1203次閱讀
    嵌入式系統(tǒng)C語(yǔ)言編程<b class='flag-5'>中</b>主要的<b class='flag-5'>錯(cuò)誤處理</b>方式

    Rust語(yǔ)言中錯(cuò)誤處理的機(jī)制

    可能的錯(cuò)誤,實(shí)際運(yùn)行仍然可能出現(xiàn)各種各樣的錯(cuò)誤,比如文件不存在、網(wǎng)絡(luò)連接失敗等等。對(duì)于這些不可預(yù)測(cè)的錯(cuò)誤,我們必須使用錯(cuò)誤處理機(jī)制來(lái)進(jìn)行
    的頭像 發(fā)表于 09-19 14:54 ?1797次閱讀

    嵌入式C編程常用的異常錯(cuò)誤處理

    嵌入式C編程,異常錯(cuò)誤處理是確保系統(tǒng)穩(wěn)定性和可靠性的重要部分。以下是一些常見的異常錯(cuò)誤處理方法及其詳細(xì)說(shuō)明和示例: 1. 斷言 (Assertions) 斷言用于在開發(fā)階段捕獲程
    發(fā)表于 08-06 14:32

    labviEW錯(cuò)誤處理的問(wèn)題

    為什么這個(gè)程序在啟用自動(dòng)錯(cuò)誤處理和C:\data.txt不存在的情況下,沒有顯示錯(cuò)誤對(duì)話框啊?
    發(fā)表于 04-01 10:03

    AF錯(cuò)誤處理

    想問(wèn)一下關(guān)于AF的錯(cuò)誤處理,例如我進(jìn)行串口通訊,打開串口錯(cuò)誤,但是我不想停止AF,想繼續(xù)嘗試連接要怎么做?
    發(fā)表于 02-03 15:44

    LabVIEW錯(cuò)誤處理

    如何合理使用 LabVIEW 的自定義錯(cuò)誤處理功能;對(duì)于可預(yù)見的錯(cuò)誤,是否可以選擇直 接忽略,或者前幾次嘗試忽略直到該特定錯(cuò)誤出現(xiàn)很多次后才通知用戶需要糾正該
    發(fā)表于 05-24 11:07 ?6次下載

    Spring Boot框架錯(cuò)誤處理

    》 《strong》翻譯《/strong》:雁驚寒《/p》 《/blockquote》《p》《em》摘要:本文通過(guò)實(shí)例介紹了使用Spring Boot在設(shè)計(jì)API的時(shí)候如何正確地對(duì)異常進(jìn)行處理。以下是譯文《/em》《/p》《p》API在提供錯(cuò)誤消息的同時(shí)進(jìn)行適當(dāng)?shù)?/div>
    發(fā)表于 09-28 15:31 ?0次下載

    嵌入式系統(tǒng)C語(yǔ)言編程錯(cuò)誤處理資料總結(jié)

    本文主要總結(jié)嵌入式系統(tǒng)C語(yǔ)言編程,主要的錯(cuò)誤處理方式。文中涉及的代碼運(yùn)行環(huán)境如下:
    發(fā)表于 11-28 10:39 ?2079次閱讀

    Rust代碼啟發(fā)之返回值異常錯(cuò)誤處理

    這樣的代碼,錯(cuò)誤處理代碼和業(yè)務(wù)邏輯交織在一起,也容易忽略處理錯(cuò)誤。以及把返回值只用于錯(cuò)誤返回,有點(diǎn)浪費(fèi)的感覺。因?yàn)楹芏鄷r(shí)候把計(jì)算結(jié)果作為返回值,更符合思考的邏輯。
    的頭像 發(fā)表于 09-22 09:24 ?2431次閱讀
    <b class='flag-5'>Rust</b>代碼啟發(fā)之返回值異常<b class='flag-5'>錯(cuò)誤處理</b>

    rust語(yǔ)言基礎(chǔ)學(xué)習(xí): rust錯(cuò)誤處理

    錯(cuò)誤是軟件不可避免的,所以 Rust 有一些處理出錯(cuò)情況的特性。在許多情況下,Rust 要求你承認(rèn)錯(cuò)誤
    的頭像 發(fā)表于 05-22 16:28 ?2453次閱讀

    RS232通信時(shí)怎么處理錯(cuò)誤?RS232通信中的錯(cuò)誤處理方法

    RS232通信時(shí)怎么處理錯(cuò)誤?RS232通信中的錯(cuò)誤處理方法? RS232通信是一種電氣標(biāo)準(zhǔn),它定義了計(jì)算機(jī)和串行通信設(shè)備之間的通信協(xié)議。盡管RS232通信很穩(wěn)定,但仍然可能會(huì)出現(xiàn)
    的頭像 發(fā)表于 10-17 16:33 ?3673次閱讀

    西門子博圖:錯(cuò)誤處理機(jī)制概覽

    可通過(guò)以下幾種不同的錯(cuò)誤處理機(jī)制進(jìn)行參數(shù)跟蹤或編程或訪問(wèn)錯(cuò)誤
    的頭像 發(fā)表于 11-25 11:35 ?3841次閱讀
    西門子博圖:<b class='flag-5'>錯(cuò)誤處理</b>機(jī)制概覽

    C語(yǔ)言中的錯(cuò)誤處理機(jī)制解析

    C 語(yǔ)言不提供對(duì)錯(cuò)誤處理的直接支持,但是作為一種系統(tǒng)編程語(yǔ)言,它以返回值的形式允許您訪問(wèn)底層數(shù)據(jù)。
    的頭像 發(fā)表于 02-26 11:19 ?718次閱讀

    socket編程錯(cuò)誤處理技巧

    Socket編程是網(wǎng)絡(luò)編程的基礎(chǔ),它允許程序之間通過(guò)TCP/IP協(xié)議進(jìn)行通信。然而,網(wǎng)絡(luò)通信是不穩(wěn)定的,可能會(huì)遇到各種問(wèn)題,如網(wǎng)絡(luò)延遲、連接中斷、數(shù)據(jù)丟失等。 錯(cuò)誤處理的重要性 提高程序的健壯性
    的頭像 發(fā)表于 11-01 17:47 ?1424次閱讀
    主站蜘蛛池模板: 日本免费一区二区老鸭窝 | 99成人在线观看 | 97影院理论片手机在线观看 | 视频在线观看免费网站 | 男人和女人在床做黄的网站 | 玖玖在线国产精品 | 日本成人a视频 | 人与性www | 在线免费观看色视频 | 国产高清免费午夜在线视频 | 性欧美日韩 | 天天拍夜夜添久久精品中文 | 成人三级在线播放线观看 | 好吊788gaoco| 凸输偷窥xxxx自由视频 | 特级全黄一级毛片免费 | 奇米影视7777久久精品 | free性欧美video| 一区二区三区四区五区 | 奇米影视四色首页手机在线 | 男男np主受高h啪啪肉 | 欧美1区| 精品久久久久久 | 五月四房婷婷 | 天天干干天天 | 天天摸夜夜爽 | 色骚网| 天天干天天操天天 | 影音先锋色偷偷米奇四色 | 欧美性三级| 日本黄色视屏 | 日本黄色免费片 | 多男一女一级淫片免费播放口 | 亚洲黄色色图 | 亚洲第8页 | 美女黄色在线看 | 四虎影视地址 | 免费观看欧美成人1314色 | 高h视频网站| 色www视频永久免费软件 | 91啪在线视频 |