自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

入門Rust的固定套路:錯誤處理模式有三大類,幫你總結(jié)了

開發(fā)
最近在學(xué)習(xí)總結(jié)Rust的各種場景的語法模式,也就是Rust寫代碼的模式。今天分享關(guān)于Rust的錯誤處理的三大類語法模式。

最近在學(xué)習(xí)總結(jié)Rust的各種場景的語法模式,也就是Rust寫代碼的模式。

今天分享關(guān)于Rust的錯誤處理的三大類語法模式。

先列出一個大綱

第一類:有意不處理錯誤,忽略錯誤

  • unwrap()
  • .fn( )? 符號,代替rust早期版本中的try!宏

第二類:對錯誤做自定義信息提示

  • 使用expect()。

第三類:推薦!根據(jù)正確和錯誤情況分開處理,錯誤還可以進(jìn)一步分流處理

  • match(包括 match處理 Result<T,E>或  match處理Option<>, 或 使用map_err())
  • 使用if let Some(value)= fn() {} else {}
  • 使用特定的函數(shù):and_then() 和 or_else()

我對Rust的錯誤處理的印象

Rust的錯誤處理方式比起Golang更靈活,可以針對錯誤和當(dāng)下代碼需要賦值前做錯誤判斷、故意忽略異常、異常時打印錯誤并終止等的不同編碼場景,選用不同的語法模式。

錯誤處理涉及到數(shù)據(jù)類型、錯誤處理的控制語法、相關(guān)的crate模塊。

Rust錯誤處理涉及到的數(shù)據(jù)類型

錯誤處理的類型1:Result

Result屬于Rust的核心crate提供的功能(core::result::Result)。Result 有2個特點(diǎn):

首先,Result<T,E> 屬于泛型,所以T和E可以是任意類型。但常見的使用模式是以T存儲正常情況的信息,E存儲錯誤和異常情況的信息。

其次,Result是枚舉類型,其內(nèi)部實(shí)際只包含:

Ok()
Err()

這兩個枚舉,所以它的實(shí)例只會是Ok()或Err()之一。

Result的代碼實(shí)現(xiàn)中就用的枚舉類型的,代碼如下:

/// Result的定義在 rust核心代碼 src/rust/library/core/src/result.rs 代碼文件中:
/// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]).
///
/// See the [module documentation](self "module documentation") for details.
#[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
#[must_use = "this `Result` may be an `Err` variant, which should be handled"]
#[rustc_diagnostic_item = "Result"]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Result<T, E> {
    /// Contains the success value
    #[lang = "Ok"]
    #[stable(feature = "rust1", since = "1.0.0")]
    Ok(#[stable(feature = "rust1", since = "1.0.0")] T),

    /// Contains the error value
    #[lang = "Err"]
    #[stable(feature = "rust1", since = "1.0.0")]
    Err(#[stable(feature = "rust1", since = "1.0.0")] E),
}

實(shí)際使用的一個例子:例如Result<String, &str> 是一個泛型類型,則此時的T類型為String,E類型為&str。它表示一個可能成功或失敗的操作的結(jié)果,其中成功時的返回類型為 String,失敗時的錯誤類型為 &str。

總結(jié)一下Result<Ok(),Err()>:  result 類型通常用于表示可能成功或失敗的操作的結(jié)果。它使用 Result<T, E> 類型來表示,其中 T 是成功時的返回類型,E 是失敗時的錯誤類型。

錯誤處理的類型2:Option

Option也是枚舉類型,其內(nèi)部實(shí)際只包含兩種值:Some()和None,這個可以從其代碼中得到印證。Option的實(shí)現(xiàn)代碼為:

/// 代碼文件 rustlib/src/rust/library/core/src/option.rs 定義了Option
/// The `Option` type. See [the module level documentation](self "the module level documentation") for more.
#[derive(Copy, PartialOrd, Eq, Ord, Debug, Hash)]
#[rustc_diagnostic_item = "Option"]
#[lang = "Option"]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Option<T> {
    /// No value.
    #[lang = "None"]
    #[stable(feature = "rust1", since = "1.0.0")]
    None,
    /// Some value of type `T`.
    #[lang = "Some"]
    #[stable(feature = "rust1", since = "1.0.0")]
    Some(#[stable(feature = "rust1", since = "1.0.0")] T),
}

Result 和 Option 有什么區(qū)別?

首先,從名稱上理解一下:

  • Result 中文意思是結(jié)果。一般表示成功或失敗,所以它的枚舉值會是Ok()和Err();
  • Option,中文意思是選項(xiàng)。那么它的側(cè)重點(diǎn)不是成功失敗,而是不同的選項(xiàng)(有選項(xiàng)則為Some()、無選項(xiàng)則為None),所以它的枚舉值也很清楚,只有Some()和None兩個值。

其次,它們之間可以互相轉(zhuǎn)化。對于錯誤處理來說,match處理Result或Option時,都要處理錯誤或None等異常值,就實(shí)現(xiàn)了Rust的最重要的錯誤處理邏輯。

錯誤處理的控制語法的具體分析和舉例

1.Rust的第一類錯誤處理模式:忽略錯誤,不處理錯誤:

(1) unwrap()

在 Rust 中,unwrap() 方法用于從 Result 類型中提取成功時的返回值。如果 Result 類型的值是 Ok(表示成功),則 unwrap() 方法將返回 T;如果 Result 類型的值是 Err(表示失?。?,則 unwrap() 方法將觸發(fā)一個 panic,拋出一個 E 類型的錯誤。如果您在調(diào)用 unwrap() 方法時遇到錯誤,說明您正在處理一個 Err 類型的值,即失敗的情況。在這種情況下,您應(yīng)該使用其他方法來處理錯誤,而不是直接使用 unwrap() 方法。總之,在處理 Result 類型時,應(yīng)該始終考慮可能的失敗情況,并使用適當(dāng)?shù)姆椒▉硖幚礤e誤。直接使用 unwrap() 方法可能會導(dǎo)致程序崩潰(panic),因此應(yīng)該謹(jǐn)慎使用。只應(yīng)該在非生產(chǎn)的代碼中使用。

(2) .fn()?符號

這個符號在Rust中的術(shù)語是“提前返回選項(xiàng)”(early return option),作用等同于unwrap()。只允許用于返回Result<>或Option<>類型的函數(shù)之后。在rust的早期版本中,有個try!宏具有等效的功能。

代碼演示:(演示打開文件,返回Result<File, Error> 類型的值,然后可以被main()中的match方式處理):

use std::fs::File;
use std::io::Error;

fn open_file(file_path: &str) -> Result<File, Error> {
    let mut file = File::open(file_path)?;
    Ok(file)
    
}

這段函數(shù)內(nèi)部使用File::open(file_path)?; 打開指定路徑的文件,open()是rust的內(nèi)部函數(shù),原始定義為:

pub fn open<P>(path: P) -> io::Result<File>

而演示代碼中有意忽略了錯誤的情況,以?結(jié)尾,來調(diào)用open()函數(shù):

let mut file = File::open(file_path)?;

2.Rust的第二類錯誤處理模式:對錯誤做自定義信息提示:

expect() 可作為代替unwrap()或 ? 相比unwrap(), expect()是一個更好的選擇,因?yàn)樗试S發(fā)生錯誤時打印一個簡單的消息并終止運(yùn)行。

3.Rust的第三類錯誤處理模式(推薦?。?/h4>

根據(jù)正確和錯誤情況分開處理,錯誤還可以進(jìn)一步分流處理。

(1) match,根據(jù)正確和錯誤情況分開處理。

  • 使用match 分流處理 Result<T,E>中包含錯誤的情況處理:
use std::fs::File;
use std::io::Error;

/// 演示打開文件,返回Result<File, Error> 類型的值,然后被main()中的match方式處理
fn open_file(file_path: &str) -> Result<File, Error> {
    let mut file = File::open(file_path)?;
    Ok(file)
}

fn main() {
    let file_path = "file.txt";
    let file = open_file(file_path);
    match file {
        Ok(file) => println!("文件打開成功 {:?}", file),
        Err(error) => println!("文件打開失敗 {}", error),
    }
}
  • 使用 match 分流處理 Option<>包含錯誤的情況處理:
use std::fs::File;
use std::io::ErrorKind;
use std::io::{Error, Read};

/// 演示文件打開時 如何返回Option<T> 類型值
fn open_file(file_path: &str) -> Option<File> {
    let mut file = File::open(file_path).unwrap();
    Some(file)
}

/// 演示 match 如何處理 Option<T> 類型值,其中有None類型的情況
fn read_file(file: Option<File>) -> Result<String, Error> {
    match file {
        //處理文件的正常情況
        Some(mut file) => {
            let mut buffer = String::new();
            let file_content = file.read_to_string(&mut buffer);
            Ok(buffer)
        }
        //處理文件的異常情況
        None => Err(Error::new(ErrorKind::NotFound, "File not found")),
    }
}

fn main() {
    let file_path = "file.txt";
    let file = open_file(&file_path);
    let strings_in_file = read_file(file);

    /// 在文件 file.txt 不存在的情況下,以下代碼會導(dǎo)致軟件崩潰。
    println!("{}", strings_in_file.unwrap());

    ///echo "1111">> file.txt
    /// 創(chuàng)建 file.txt文件
    /// 然后重復(fù)上面代碼
}
  • 使用 map_err() 鏈?zhǔn)教幚?/li>

map_err()  將在以后發(fā)布的文章中再講解。本文不做詳細(xì)介紹。

(2) if let,適合直接在賦值前做錯誤處理。代碼模式為:

let  final_value = if let Some(T) = Rust語句 {
    //語句正確和成功的情況,如獲取有效數(shù)據(jù),將作為作用域的返回值賦值給final_value 
} else {
    //錯誤或異常的情況的處理,如賦值為"",同樣會作為作用域的返回值賦值給 final_value 
}

以下是一些常見的處理錯誤的方法:使用 match 表達(dá)式:通過使用 match 表達(dá)式,您可以根據(jù) Result 類型的值來執(zhí)行不同的操作。如果是 Ok 類型,可以提取成功的值;如果是 Err 類型,可以處理錯誤。使用 map_err() 方法:map_err() 方法可以將 Err 類型的值轉(zhuǎn)換為另一種錯誤類型,并返回一個新的 Result 類型。使用 and_then() 或 or_else() 方法:這些方法可以在成功或失敗的情況下執(zhí)行不同的操作,并返回一個新的 Result 類型。

(3) 使用特定的函數(shù):and_then() 和 or_else()和 ok_or()

這3個函數(shù)在Rust中的術(shù)語為組合算子,如果你已理解C/C++中的 && 和 ||或 Python中的and以及or語法的意義,那么你大概已經(jīng)理解了 and_then() 這3個函數(shù)的意思。比如 and_then()是當(dāng)調(diào)用者為true或調(diào)用者為正常的時候,才會調(diào)用and_then(...)函數(shù)。那么對于錯誤處理就非常有用。

下面的代碼例子演示了烹飪的邏輯:當(dāng)有食材的時候,才能按照食譜制作好菜品。隱含的意思就是(錯誤的情況下),沒有食材的情況下,就不用照著食譜做菜了。

#![allow(dead_code)]
#[derive(Debug)] enum Food { CordonBleu, Steak, Sushi }
#[derive(Debug)] enum Day { Monday, Tuesday, Wednesday }
// 我們沒有原材料(ingredient)來制作壽司。
fn have_ingredients(food: Food) -> Option<Food> {
    match food {
        Food::Sushi => None,
        _           => Some(food),
    }
}
// 我們擁有全部食物的食譜,除了欠缺高超的烹飪手藝。
fn have_recipe(food: Food) -> Option<Food> {
    match food {
        Food::CordonBleu => None,
        _                => Some(food),
    }
}
// 做一份好菜,我們需要原材料和食譜這兩者。
// 我們可以借助一系列 `match` 來表達(dá)相應(yīng)的邏輯:
// (原文:We can represent the logic with a chain of `match`es:)
fn cookable_v1(food: Food) -> Option<Food> {
    match have_ingredients(food) {
        None       => None,
        Some(food) => match have_recipe(food) {
            None       => None,
            Some(food) => Some(food),
        },
    }
}
// 這可以使用 `and_then()` 方便重寫出更緊湊的代碼:
fn cookable_v2(food: Food) -> Option<Food> {
    have_ingredients(food).and_then(have_recipe)
}
fn eat(food: Food, day: Day) {
    match cookable_v2(food) {
        Some(food) => println!("Yay! On {:?} we get to eat {:?}.", day, food),
        None       => println!("Oh no. We don't get to eat on {:?}?", day),
    }
}
fn main() {
    let (cordon_bleu, steak, sushi) = (Food::CordonBleu, Food::Steak, Food::Sushi);
    eat(cordon_bleu, Day::Monday);
    eat(steak, Day::Tuesday);
    eat(sushi, Day::Wednesday);
}

責(zé)任編輯:趙寧寧 來源: 深入理解Linux
相關(guān)推薦

2025-02-10 09:49:00

2023-03-10 08:48:29

2009-11-06 11:21:21

WCF事務(wù)管理器

2021-04-14 07:08:14

Nodejs錯誤處理

2020-12-17 06:25:05

Gopanic 模式

2024-03-27 08:18:02

Spring映射HTML

2024-11-27 10:28:22

Rust繼承識別

2023-02-20 08:00:02

Rust語言系統(tǒng)

2014-11-17 10:05:12

Go語言

2020-03-09 08:00:00

技術(shù)管理套路

2021-04-29 09:02:44

語言Go 處理

2010-03-22 14:54:35

2023-12-26 22:05:53

并發(fā)代碼goroutines

2010-04-21 16:47:05

Oracle數(shù)據(jù)

2022-11-16 08:41:43

2009-08-05 16:04:50

2023-10-28 16:30:19

Golang開發(fā)

2010-06-01 16:14:04

2010-05-12 14:05:54

MySQL安裝

2009-06-19 16:20:14

ASP.NET錯誤處理
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號