Manejo de errores en Rust con el signo de interrogación

Beginner

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

Introducción

En este laboratorio, aprenderemos sobre el operador ? en Rust, que nos permite simplificar el manejo de errores devolviendo Err en lugar de causar un panic, y también exploraremos la macro try!, que lograba una funcionalidad similar antes de que se introdujera ?.

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.

Presentando ?

A veces solo queremos la simplicidad de unwrap sin la posibilidad de un panic. Hasta ahora, unwrap nos ha obligado a anidar cada vez más profundamente cuando lo que realmente queríamos era obtener la variable fuera. Esto es exactamente el propósito de ?.

Al encontrar un Err, hay dos acciones válidas que se pueden tomar:

  1. panic! que ya decidimos tratar de evitar si es posible
  2. return porque un Err significa que no se puede manejar

? es casi[^†] exactamente equivalente a un unwrap que returns en lugar de panicar en Errs. Veamos cómo podemos simplificar el ejemplo anterior que usaba combinadores:

use std::num::ParseIntError;

fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> {
    let first_number = first_number_str.parse::<i32>()?;
    let second_number = second_number_str.parse::<i32>()?;

    Ok(first_number * second_number)
}

fn print(result: Result<i32, ParseIntError>) {
    match result {
        Ok(n)  => println!("n es {}", n),
        Err(e) => println!("Error: {}", e),
    }
}

fn main() {
    print(multiply("10", "2"));
    print(multiply("t", "2"));
}

La macro try!

Antes de que existiera ?, la misma funcionalidad se lograba con la macro try!. Ahora se recomienda el operador ?, pero es posible que aún encuentres try! al revisar código antiguo. La misma función multiply del ejemplo anterior se vería así usando try!:

// Para compilar y ejecutar este ejemplo sin errores, mientras se usa Cargo, cambia el valor
// del campo `edition`, en la sección `[package]` del archivo `Cargo.toml`, a "2015".

use std::num::ParseIntError;

fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> {
    let first_number = try!(first_number_str.parse::<i32>());
    let second_number = try!(second_number_str.parse::<i32>());

    Ok(first_number * second_number)
}

fn print(result: Result<i32, ParseIntError>) {
    match result {
        Ok(n)  => println!("n es {}", n),
        Err(e) => println!("Error: {}", e),
    }
}

fn main() {
    print(multiply("10", "2"));
    print(multiply("t", "2"));
}

Resumen

¡Felicidades! Has completado el laboratorio Presentando ?. Puedes practicar más laboratorios en LabEx para mejorar tus habilidades.