Explorando el Tipo Result de Rust

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, exploraremos el tipo Result en Rust, que proporciona una forma de manejar errores potenciales en lugar de la posible ausencia de un valor como el tipo Option. El tipo Result puede tener dos resultados: Ok(T) para un resultado exitoso con el elemento T, y Err(E) para un error con el elemento E. Veremos cómo usar Result en ejemplos de código y cómo se puede usar como tipo de retorno de la función main para manejar errores y proporcionar un mensaje de error más específico.

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/FunctionsandClosuresGroup(["Functions and Closures"]) rust(("Rust")) -.-> rust/MemorySafetyandManagementGroup(["Memory Safety and Management"]) rust(("Rust")) -.-> rust/ErrorHandlingandDebuggingGroup(["Error Handling and Debugging"]) 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/ErrorHandlingandDebuggingGroup -.-> rust/error_propagation("Error Propagation") subgraph Lab Skills rust/variable_declarations -.-> lab-99239{{"Explorando el Tipo Result de Rust"}} rust/integer_types -.-> lab-99239{{"Explorando el Tipo Result de Rust"}} rust/string_type -.-> lab-99239{{"Explorando el Tipo Result de Rust"}} rust/function_syntax -.-> lab-99239{{"Explorando el Tipo Result de Rust"}} rust/expressions_statements -.-> lab-99239{{"Explorando el Tipo Result de Rust"}} rust/lifetime_specifiers -.-> lab-99239{{"Explorando el Tipo Result de Rust"}} rust/error_propagation -.-> lab-99239{{"Explorando el Tipo Result de Rust"}} end

Result

Result es una versión más compleja del tipo Option que describe posibles errores en lugar de posibles ausencias.

Es decir, Result<T, E> puede tener uno de dos resultados:

  • Ok(T): Se encontró un elemento T
  • Err(E): Se encontró un error con el elemento E

Por convención, el resultado esperado es Ok mientras que el resultado inesperado es Err.

Como Option, Result tiene muchos métodos asociados. unwrap(), por ejemplo, produce el elemento T o causa un panic. Para el manejo de casos, hay muchos combinadores entre Result y Option que se superponen.

Al trabajar con Rust, es probable que encuentres métodos que devuelven el tipo Result, como el método parse(). No siempre es posible analizar una cadena en el otro tipo, por lo que parse() devuelve un Result que indica un posible error.

Veamos qué pasa cuando analizamos correctamente e incorrectamente una cadena con parse():

fn multiply(first_number_str: &str, second_number_str: &str) -> i32 {
    // Intentemos usar `unwrap()` para extraer el número. ¿Nos causará problemas?
    let first_number = first_number_str.parse::<i32>().unwrap();
    let second_number = second_number_str.parse::<i32>().unwrap();
    first_number * second_number
}

fn main() {
    let twenty = multiply("10", "2");
    println!("double is {}", twenty);

    let tt = multiply("t", "2");
    println!("double is {}", tt);
}

En el caso en que no se tenga éxito, parse() nos deja con un error para que unwrap() lance un panic. Además, el panic sale de nuestro programa y proporciona un mensaje de error desagradable.

Para mejorar la calidad de nuestro mensaje de error, deberíamos ser más específicos sobre el tipo de retorno y considerar manejar explícitamente el error.

Usando Result en main

El tipo Result también puede ser el tipo de retorno de la función main si se especifica explícitamente. Normalmente, la función main tendrá la forma:

fn main() {
    println!("Hello World!");
}

Sin embargo, main también puede tener un tipo de retorno de Result. Si se produce un error dentro de la función main, devolverá un código de error e imprimirá una representación de depuración del error (usando el trato [Debug]). El siguiente ejemplo muestra un escenario de este tipo y toca aspectos cubiertos en [la siguiente sección].

use std::num::ParseIntError;

fn main() -> Result<(), ParseIntError> {
    let number_str = "10";
    let number = match number_str.parse::<i32>() {
        Ok(number)  => number,
        Err(e) => return Err(e),
    };
    println!("{}", number);
    Ok(())
}

Resumen

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