← Back to Rust Course | Chapter 10: Error Handling | Lesson 5 of 6

Error Propagation के Patterns

Error propagation एक problem को chain में ऊपर पास करना है जो भी इस बारे में decide करने के लिए सबसे अच्छी तरह equipped है कि क्या करना है।
Syntax
rust
fn name() -> Result<T, Box<dyn Error>> {
    let value = step()?;
    Ok(value)
}

impl From<Source> for NameError {
    fn from(e: Source) -> Self { NameError::Variant(e) }
}

Propagating with ? Across Functions

एक helper function ? के साथ एक error propagate कर सकता है, इसके caller (या caller के caller) को आखिरकार यह decide करने देते हुए कि कैसे react करना है, बजाय वह decision बहुत जल्दी लेने के।

उदाहरण: Propagating with ? Across Functions

markup
// Define the function `parse_positive` taking `s` and returning a `Result<i32, String>`
fn parse_positive(s: &str) -> Result<i32, String> {
    // Declare an immutable variable `n` (an integer), set to `s.parse().map_err(|_| String::from("not a number"))?`
    let n: i32 = s.parse().map_err(|_| String::from("not a number"))?;
    // Check whether `n < 0`
    if n < 0 {
        // Return `Err(String::from("must be positive"))` from this function
        return Err(String::from("must be positive"));
    }
    Ok(n)
}

// Entry point: execution of the program starts here
fn main() {
    // Print "{:?}" to the console, substituting in `parse_positive("5")` (with a trailing newline)
    println!("{:?}", parse_positive("5"));
    // Print "{:?}" to the console, substituting in `parse_positive("-3")` (with a trailing newline)
    println!("{:?}", parse_positive("-3"));
}

Using Box<dyn Error> for Multiple Error Types

जब कोई function कई unrelated तरीकों से fail हो सकता है (जैसे parsing errors और custom validation errors), Box<dyn std::error::Error> return करना इसे एक flexible return type के तहत unify करने देता है।

उदाहरण: Using Box<dyn Error> for Multiple Error Types

markup
// Bring `std::error::Error` into scope
use std::error::Error;

// Define the function `parse_and_check` taking `s` and returning a `Result<i32, Box<dyn Error>>`
fn parse_and_check(s: &str) -> Result<i32, Box<dyn Error>> {
    // Declare an immutable variable `n` (an integer), set to `s.parse()?`
    let n: i32 = s.parse()?;
    Ok(n * 2)
}

// Define the function `main` with no parameters and returning a `Result<(), Box<dyn Error>>`
fn main() -> Result<(), Box<dyn Error>> {
    // Declare an immutable variable `value`, set to `parse_and_check("21")?`
    let value = parse_and_check("21")?;
    // Print "Value: {}" to the console, substituting in `value` (with a trailing newline)
    println!("Value: {}", value);
    Ok(())
}

Adding Context While Propagating

एक middle-layer function एक error catch कर सकता है, map_err उपयोग करके इसे ज़्यादा context से wrap कर सकता है, और फिर enriched error को आगे ऊपर propagate कर सकता है, callers को क्या हुआ इसकी clearer picture देते हुए।

उदाहरण: Adding Context While Propagating

markup
// Define the function `load_setting` taking `raw` and returning a `Result<i32, String>`
fn load_setting(raw: &str) -> Result<i32, String> {
    raw.parse::<i32>().map_err(|e| format!("failed to load setting: {}", e))
}

// Entry point: execution of the program starts here
fn main() {
    // Match on `load_setting("abc")` and branch by pattern
    match load_setting("abc") {
        Ok(v) => println!("Setting: {}", v),
        Err(e) => println!("{}", e),
    }
}

main Returning a Result

Rust का main function खुद एक Result return कर सकता है, top-level program को ? सीधे उपयोग करने देते हुए और अगर कुछ fail हो तो अपने आप एक साफ़ error message print करते हुए।

उदाहरण: main Returning a Result

markup
// Define the function `main` with no parameters and returning a `Result<(), std::num::ParseIntError>`
fn main() -> Result<(), std::num::ParseIntError> {
    // Declare an immutable variable `value` (an integer), set to `"99".parse()?`
    let value: i32 = "99".parse()?;
    // Print "Parsed: {}" to the console, substituting in `value` (with a trailing newline)
    println!("Parsed: {}", value);
    Ok(())
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
आम गलतियां
  1. किसी low-level helper function के अंदर हर possible error को handle करना बजाय इसे किसी caller तक bubble up करने देने के जिसके पास ज़्यादा context हो।
  2. यह भूल जाना कि Box<dyn Error> एक आम flexible return type है जब कोई function कई अलग-अलग unrelated error types produce कर सकता है।
  3. किसी call chain में गहराई में ? से error को ऊपर propagate करने के बजाय .unwrap() overuse करना, जो पूरे program को crash करता है बजाय किसी caller को decide करने देने के।
चैप्टर सारांश
  • ? से errors को ऊपर propagate करना higher-level code को यह decide करने देता है कि failures को कैसे handle या report करना है।
  • Box<dyn std::error::Error> उन functions के लिए एक आम return type है जो एक से ज़्यादा distinct तरीके से fail हो सकते हैं।
  • Layered functions हर एक error को आगे call stack में ऊपर propagate करने से पहले अपना context जोड़ सकते हैं।
  • अच्छी error propagation low-level functions को simple रखती है जबकि decision-making को higher levels पर concentrate करती है।
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.