0Pricing
Learn Rust Coding · Lektion

Robuste Fehlerbehandlung mit `Result`

Implementieren Sie idiomatische Fehlerbehandlung mit dem `Result`-Enum, dem `?`-Operator und eigenen Fehlertypen für robuste Anwendungen.

Robuste Fehlerbehandlung mit `Result` ist eine kostenlose Learn Rust Coding-Lektion auf CoddyKit. Dies ist Lektion 3 von 3. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Learn Rust Coding-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Learn Rust Coding-Kurs umfasst insgesamt 3 Lektionen.

Teile dieser Lektion wurden noch nicht übersetzt und werden auf Englisch angezeigt.

Handling Errors in Rust

Errors are a part of programming. In Rust, we distinguish between two main types: recoverable and unrecoverable errors.

  • Unrecoverable errors usually signal bugs, causing the program to stop with panic!.
  • Recoverable errors mean something went wrong but can be handled, like a file not found.

Rust helps you deal with recoverable errors gracefully.

`panic!` vs `Result`

When an unrecoverable error occurs, Rust calls the panic! macro. This unwinds the stack and exits your program, usually printing an error message.

For recoverable errors, Rust uses the Result enum. This enum tells you if an operation succeeded (Ok) or failed (Err), letting your program decide what to do next.

The `Result` Enum

The Result enum is defined conceptually as:

enum Result<T, E> {
  Ok(T),
  Err(E),
}

  • T represents the type of value returned on success.
  • E represents the type of error returned on failure.

It's a powerful way to explicitly state that a function might fail.

Matching on `Result`

The most common way to handle a Result is using a match expression. This allows you to execute different code blocks based on whether the Result is Ok or Err.

Try running this example that attempts to parse a number:

fn parse_and_add(text: &str) -> Result<i32, std::num::ParseIntError> {
    text.parse::<i32>()
}

fn main() {
    let num_str = "123";
    let result = parse_and_add(num_str);

    match result {
        Ok(num) => println!("Parsed number: {}", num),
        Err(e) => println!("Error parsing: {}", e),
    }

    let bad_str = "abc";
    let bad_result = parse_and_add(bad_str);

    match bad_result {
        Ok(num) => println!("Parsed number: {}", num),
        Err(e) => println!("Error parsing: {}", e),
    }
}

Unwrapping Results (Carefully!)

Sometimes you might be certain an operation won't fail, or you want your program to crash if it does. Methods like unwrap() and expect() extract the Ok value.

  • unwrap(): Returns the Ok value or panics if it's Err.
  • expect("message"): Same as unwrap() but lets you provide a custom panic message.

Use these sparingly, mainly in tests or when failure is truly unrecoverable.

Introducing the `?` Operator

Writing match statements for every Result can get repetitive. The ? operator provides a concise shortcut for error propagation.

When placed after an expression that returns a Result, ? does two things:

  • If the Result is Err, it immediately returns the Err from the current function.
  • If the Result is Ok, it unwraps the Ok value and continues execution.

`?` Operator in Action

The ? operator makes functions that might fail much cleaner to write. Remember, the function using ? must itself return a Result (or Option).

Observe how ? simplifies error handling in this file reading example:

use std::fs::File;
use std::io::{self, Read};

fn read_username_from_file() -> Result<String, io::Error> {
    let mut f = File::open("hello.txt")?; // Propagates error if file not found
    let mut s = String::new();
    f.read_to_string(&mut s)?; // Propagates error if read fails
    Ok(s)
}

fn main() {
    // Create a dummy file for the example to work
    // In a real scenario, this file might not exist
    std::fs::write("hello.txt", "CoddyKit User").unwrap();

    match read_username_from_file() {
        Ok(username) => println!("Username: {}", username),
        Err(e) => println!("Error reading username: {}", e),
    }

    // Clean up the dummy file
    std::fs::remove_file("hello.txt").unwrap();
}

Custom Error Types

Sometimes, built-in error types aren't specific enough. You can define your own custom error types using enums to represent different failure modes of your application.

This makes your error messages clearer and allows callers to handle specific errors differently.

A common pattern is to create an enum that lists all possible errors a function or module can produce.

Making `?` Work with Custom Errors

For the ? operator to automatically convert a lower-level error (like io::Error) into your custom error type, your custom error enum must implement the From trait for that lower-level error.

This tells Rust how to convert one error type into another, making error propagation seamless.

use std::io;
use std::fs::File;
use std::io::Read;

#[derive(Debug)]
enum MyError {
    Io(io::Error),
    Parse(std::num::ParseIntError)
}

impl From<io::Error> for MyError {
    fn from(error: io::Error) -> Self {
        MyError::Io(error)
    }
}

impl From<std::num::ParseIntError> for MyError {
    fn from(error: std::num::ParseIntError) -> Self {
        MyError::Parse(error)
    }
}

fn read_config(path: &str) -> Result<i32, MyError> {
    let mut file = File::open(path)?; // io::Error converted to MyError::Io
    let mut contents = String::new();
    file.read_to_string(&mut contents)?; // io::Error converted to MyError::Io
    let value = contents.trim().parse::<i32>()?; // ParseIntError converted to MyError::Parse
    Ok(value)
}

fn main() {
    // Create a dummy file for the example
    std::fs::write("config.txt", "123").unwrap();

    match read_config("config.txt") {
        Ok(val) => println!("Config value: {}", val),
        Err(e) => println!("Failed to read config: {:?}", e),
    }

    std::fs::remove_file("config.txt").unwrap(); // Clean up

    // Example with a non-existent file
    match read_config("non_existent.txt") {
        Ok(val) => println!("Config value: {}", val),
        Err(e) => println!("Failed to read config: {:?}", e),
    }
}

Check Your Understanding

Consider the following Rust code snippet. What will be the output if the file data.txt does NOT exist?

Recap: Robust Error Handling

You've mastered robust error handling in Rust!

  • Result Enum: Distinguishes between Ok(T) for success and Err(E) for failure.
  • match: The fundamental way to handle Result variants.
  • ? Operator: A powerful shortcut for propagating Err values up the call stack.
  • Custom Errors: Define your own error types using enums for clarity and specific handling.
  • From Trait: Enables seamless conversion of lower-level errors into your custom error types when using ?.

Next, explore advanced type system features!

Häufig gestellte Fragen

Ist die Lektion „Robuste Fehlerbehandlung mit `Result`“ kostenlos?

Ja — der vollständige Text von „Robuste Fehlerbehandlung mit `Result`“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Learn Rust Coding-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Learn Rust Coding-Kurs umfasst insgesamt 3 Lektionen.

Was lerne ich in „Robuste Fehlerbehandlung mit `Result`“?

Implementieren Sie idiomatische Fehlerbehandlung mit dem `Result`-Enum, dem `?`-Operator und eigenen Fehlertypen für robuste Anwendungen. Du übst Learn Rust Coding mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Learn Rust Coding zu starten?

Keine Vorkenntnisse erforderlich. Learn Rust Coding auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 3.

Wie lange dauert die Lektion „Robuste Fehlerbehandlung mit `Result`“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Learn Rust Coding-Lektion Code schreiben und ausführen?

Ja. Jede Learn Rust Coding-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Code mit Modulen organisieren
  2. Abhängigkeiten mit Crates verwalten
  3. Robuste Fehlerbehandlung mit `Result`
← Zurück zu Learn Rust Coding