Definieren eines Fehlertyps

RustRustBeginner
Jetzt üben

This tutorial is from open-source community. Access the source code

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

In diesem Lab betrachten wir, wie man in Rust einen benutzerdefinierten Fehlertyp definiert und welche Schlüsselmerkmale einen guten Fehlertyp ausmachen, wie z. B. die Darstellung unterschiedlicher Fehler mit demselben Typ, die Bereitstellung von klaren Fehlermeldungen, das einfache Vergleichen mit anderen Typen und die Möglichkeit, Informationen über den Fehler zu speichern. Wir betrachten auch ein Beispielcode, der die Implementierung eines benutzerdefinierten Fehlertyps und seine Verwendung in Fehlerbehandlungsszenarien demonstriert.

Hinweis: Wenn das Lab keinen Dateinamen angibt, können Sie einen beliebigen Dateinamen verwenden. Beispielsweise können Sie main.rs verwenden und es mit rustc main.rs &&./main kompilieren und ausführen.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust(("Rust")) -.-> rust/MemorySafetyandManagementGroup(["Memory Safety and Management"]) rust(("Rust")) -.-> rust/DataStructuresandEnumsGroup(["Data Structures and Enums"]) rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) rust(("Rust")) -.-> rust/BasicConceptsGroup(["Basic Concepts"]) rust(("Rust")) -.-> rust/DataTypesGroup(["Data Types"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/DataTypesGroup -.-> rust/integer_types("Integer Types") rust/DataTypesGroup -.-> rust/string_type("String Type") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("Function Syntax") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") rust/MemorySafetyandManagementGroup -.-> rust/lifetime_specifiers("Lifetime Specifiers") rust/DataStructuresandEnumsGroup -.-> rust/method_syntax("Method Syntax") rust/AdvancedTopicsGroup -.-> rust/traits("Traits") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/variable_declarations -.-> lab-99247{{"Definieren eines Fehlertyps"}} rust/integer_types -.-> lab-99247{{"Definieren eines Fehlertyps"}} rust/string_type -.-> lab-99247{{"Definieren eines Fehlertyps"}} rust/function_syntax -.-> lab-99247{{"Definieren eines Fehlertyps"}} rust/expressions_statements -.-> lab-99247{{"Definieren eines Fehlertyps"}} rust/lifetime_specifiers -.-> lab-99247{{"Definieren eines Fehlertyps"}} rust/method_syntax -.-> lab-99247{{"Definieren eines Fehlertyps"}} rust/traits -.-> lab-99247{{"Definieren eines Fehlertyps"}} rust/operator_overloading -.-> lab-99247{{"Definieren eines Fehlertyps"}} end

Ein Fehlertyp definieren

Manchmal vereinfacht es den Code, alle verschiedenen Fehler mit einem einzigen Fehlertyp zu maskieren. Wir werden dies anhand eines benutzerdefinierten Fehlers zeigen.

Rust ermöglicht es uns, unsere eigenen Fehlertypen zu definieren. Im Allgemeinen ist ein "guter" Fehlertyp:

  • Stellt verschiedene Fehler mit demselben Typ dar
  • Gibt nette Fehlermeldungen an den Benutzer aus
  • Ist leicht mit anderen Typen zu vergleichen
    • Gut: Err(EmptyVec)
    • Schlecht: Err("Please use a vector with at least one element".to_owned())
  • Kann Informationen über den Fehler speichern
    • Gut: Err(BadChar(c, position))
    • Schlecht: Err("+ cannot be used here".to_owned())
  • Kombiniert sich gut mit anderen Fehlern
use std::fmt;

type Result<T> = std::result::Result<T, DoubleError>;

// Definieren Sie unsere Fehlertypen. Diese können für unsere Fehlerbehandlungsszenarien angepasst werden.
// Jetzt können wir unsere eigenen Fehler schreiben, uns auf eine zugrunde liegende Fehlerimplementierung stützen
// oder etwas dazwischen tun.
#[derive(Debug, Clone)]
struct DoubleError;

// Die Generierung eines Fehlers ist völlig getrennt von der Art, wie er angezeigt wird.
// Es ist nicht erforderlich, sich um die Verschmutzung komplexer Logik mit dem Anzeige Stil zu kümmern.
//
// Beachten Sie, dass wir keine zusätzlichen Informationen über die Fehler speichern. Dies bedeutet, dass wir nicht angeben können,
// welche Zeichenfolge fehlgeschlagen ist, ohne unsere Typen zu ändern, um diese Information zu übermitteln.
impl fmt::Display for DoubleError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "invalid first item to double")
    }
}

fn double_first(vec: Vec<&str>) -> Result<i32> {
    vec.first()
        // Ändern Sie den Fehler in unseren neuen Typ um.
     .ok_or(DoubleError)
     .and_then(|s| {
            s.parse::<i32>()
                // Aktualisieren Sie auch hier auf den neuen Fehlertyp.
             .map_err(|_| DoubleError)
             .map(|i| 2 * i)
        })
}

fn print(result: Result<i32>) {
    match result {
        Ok(n) => println!("The first doubled is {}", n),
        Err(e) => println!("Error: {}", e),
    }
}

fn main() {
    let numbers = vec!["42", "93", "18"];
    let empty = vec![];
    let strings = vec!["tofu", "93", "18"];

    print(double_first(numbers));
    print(double_first(empty));
    print(double_first(strings));
}

Zusammenfassung

Herzlichen Glückwunsch! Sie haben das Lab "Defining an Error Type" abgeschlossen. Sie können in LabEx weitere Labs absolvieren, um Ihre Fähigkeiten zu verbessern.