Definiendo un Tipo de Error

RustRustBeginner
Practicar Ahora

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

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

En este laboratorio, estamos viendo cómo definir un tipo de error personalizado en Rust y las características clave que hacen de un buen tipo de error, como representar diferentes errores con el mismo tipo, proporcionar mensajes de error claros, facilitar la comparación con otros tipos y la capacidad de contener información sobre el error. También examinamos un código de ejemplo que demuestra la implementación de un tipo de error personalizado y su uso en escenarios de manejo de errores.

Nota: Si el laboratorio no especifica un nombre de archivo, puede usar cualquier nombre de archivo que desee. Por ejemplo, puede usar main.rs, compilar y ejecutarlo con rustc main.rs &&./main.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/BasicConceptsGroup(["Basic Concepts"]) rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust(("Rust")) -.-> rust/DataStructuresandEnumsGroup(["Data Structures and Enums"]) rust(("Rust")) -.-> rust/DataTypesGroup(["Data Types"]) rust(("Rust")) -.-> rust/MemorySafetyandManagementGroup(["Memory Safety and Management"]) rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) 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{{"Definiendo un Tipo de Error"}} rust/integer_types -.-> lab-99247{{"Definiendo un Tipo de Error"}} rust/string_type -.-> lab-99247{{"Definiendo un Tipo de Error"}} rust/function_syntax -.-> lab-99247{{"Definiendo un Tipo de Error"}} rust/expressions_statements -.-> lab-99247{{"Definiendo un Tipo de Error"}} rust/lifetime_specifiers -.-> lab-99247{{"Definiendo un Tipo de Error"}} rust/method_syntax -.-> lab-99247{{"Definiendo un Tipo de Error"}} rust/traits -.-> lab-99247{{"Definiendo un Tipo de Error"}} rust/operator_overloading -.-> lab-99247{{"Definiendo un Tipo de Error"}} end

Definiendo un tipo de error

A veces, simplifica el código enmascarar todos los diferentes errores con un solo tipo de error. Lo demostraremos con un error personalizado.

Rust nos permite definir nuestros propios tipos de error. En general, un "buen" tipo de error:

  • Representa diferentes errores con el mismo tipo
  • Muestra mensajes de error agradables al usuario
  • Es fácil de comparar con otros tipos
    • Bueno: Err(EmptyVec)
    • Malo: Err("Please use a vector with at least one element".to_owned())
  • Puede contener información sobre el error
    • Bueno: Err(BadChar(c, position))
    • Malo: Err("+ cannot be used here".to_owned())
  • Se combina bien con otros errores
use std::fmt;

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

// Definimos nuestros tipos de error. Estos pueden ser personalizados para nuestros casos de manejo de errores.
// Ahora podremos escribir nuestros propios errores, delegar en una implementación de error subyacente
// o hacer algo intermedio.
#[derive(Debug, Clone)]
struct DoubleError;

// La generación de un error es completamente separada de cómo se muestra.
// No es necesario preocuparse por enredar la lógica compleja con el estilo de visualización.
//
// Nota que no almacenamos ninguna información adicional sobre los errores. Esto significa que no podemos
// indicar qué cadena falló al analizar sin modificar nuestros tipos para transportar esa información.
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()
        // Cambiamos el error al nuestro nuevo tipo.
     .ok_or(DoubleError)
     .and_then(|s| {
            s.parse::<i32>()
                // Actualizamos también al nuevo tipo de error aquí.
             .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));
}

Resumen

¡Felicitaciones! Has completado el laboratorio Definiendo un Tipo de Error. Puedes practicar más laboratorios en LabEx para mejorar tus habilidades.