En Rust, el manejo de errores es una parte fundamental del lenguaje, diseñada para ayudar a los desarrolladores a escribir código robusto y seguro. Uno de los mecanismos principales para manejar errores es el tipo Result
. En esta sección, aprenderemos qué es Result
, cómo usarlo y cómo manejar errores de manera efectiva.
¿Qué es Result
?
El tipo Result
es una enumeración (enum) que se utiliza para representar el resultado de una operación que puede fallar. Tiene dos variantes:
Ok(T)
: Indica que la operación fue exitosa y contiene un valor de tipoT
.Err(E)
: Indica que la operación falló y contiene un valor de tipoE
, que describe el error.
La definición de Result
se ve así:
Uso Básico de Result
Veamos un ejemplo simple de cómo usar Result
en una función que intenta dividir dos números:
fn divide(dividend: f64, divisor: f64) -> Result<f64, String> { if divisor == 0.0 { Err(String::from("División por cero")) } else { Ok(dividend / divisor) } } fn main() { let result = divide(10.0, 2.0); match result { Ok(value) => println!("Resultado: {}", value), Err(e) => println!("Error: {}", e), } }
Explicación del Código
-
Definición de la Función
divide
:- La función
divide
toma dos parámetrosdividend
ydivisor
de tipof64
. - Retorna un
Result<f64, String>
, dondef64
es el tipo del valor exitoso yString
es el tipo del error.
- La función
-
Manejo del Error:
- Si el
divisor
es0.0
, la función retornaErr
con un mensaje de error. - Si no, retorna
Ok
con el resultado de la división.
- Si el
-
Uso de
match
para Manejar el Resultado:- En
main
, se llama adivide
y se usa unmatch
para manejar las variantesOk
yErr
.
- En
Métodos Comunes de Result
Rust proporciona varios métodos útiles para trabajar con Result
. Aquí hay algunos de los más comunes:
unwrap
El método unwrap
extrae el valor contenido en Ok
o hace que el programa entre en pánico si es Err
.
fn main() { let result = divide(10.0, 2.0); let value = result.unwrap(); println!("Resultado: {}", value); }
unwrap_or
El método unwrap_or
proporciona un valor predeterminado en caso de error.
fn main() { let result = divide(10.0, 0.0); let value = result.unwrap_or(0.0); println!("Resultado: {}", value); }
unwrap_or_else
El método unwrap_or_else
ejecuta una función en caso de error.
fn main() { let result = divide(10.0, 0.0); let value = result.unwrap_or_else(|e| { println!("Error: {}", e); 0.0 }); println!("Resultado: {}", value); }
Ejercicio Práctico
Ejercicio
Escribe una función llamada read_file
que intente leer el contenido de un archivo y retorne un Result<String, std::io::Error>
. Usa esta función en main
y maneja el resultado adecuadamente.
use std::fs::File; use std::io::{self, Read}; fn read_file(filename: &str) -> Result<String, io::Error> { let mut file = File::open(filename)?; let mut contents = String::new(); file.read_to_string(&mut contents)?; Ok(contents) } fn main() { match read_file("example.txt") { Ok(contents) => println!("Contenido del archivo:\n{}", contents), Err(e) => println!("Error al leer el archivo: {}", e), } }
Solución Explicada
-
Importación de Módulos:
std::fs::File
para manejar archivos.std::io::{self, Read}
para manejar errores de E/S y leer archivos.
-
Definición de la Función
read_file
:- Toma un
filename
de tipo&str
. - Intenta abrir el archivo con
File::open
. El operador?
propaga el error si ocurre. - Lee el contenido del archivo en una
String
usandofile.read_to_string
. Nuevamente, el operador?
propaga el error. - Retorna el contenido del archivo envuelto en
Ok
.
- Toma un
-
Manejo del Resultado en
main
:- Usa un
match
para manejar las variantesOk
yErr
.
- Usa un
Conclusión
El tipo Result
es una herramienta poderosa en Rust para manejar errores de manera segura y explícita. Al usar Result
, puedes escribir código que maneje fallos de manera predecible y robusta. En la siguiente sección, exploraremos otro tipo importante para el manejo de errores: Option
.
Curso de Programación en Rust
Módulo 1: Introducción a Rust
- ¿Qué es Rust?
- Configuración del Entorno de Rust
- Programa "Hola, Mundo!"
- Sintaxis y Estructura Básica