Manejo de errores en Rust: try/catch y más — guía completa

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: ¿por qué Rust no usa try/catch?



En la mayoría de los lenguajes de programación (JavaScript, Python, Java) el manejo de errores se basa en el mecanismo de excepciones y la construcción try/catch. Sin embargo, en Rust este enfoque está ausente. En su lugar, los desarrolladores utilizan un potente sistema de tipos que hace que los errores sean parte de la firma de la función. Esto no es una casualidad, sino una decisión arquitectónica bien pensada: Rust busca previsibilidad y seguridad en tiempo de compilación, excluyendo caídas ocultas del programa.



En este artículo analizaremos:

  • Por qué Rust abandonó try/catch;
  • Cómo funcionan las herramientas principales: Option, Result, unwrap(), expect();
  • Qué es el operador ? (signo de interrogación);
  • Cuándo usar panic! y la macro try! (obsoleta);
  • Prácticas modernas de manejo de errores en Rust 2024.


1. Fundamentos: Option y Result — los dos tipos principales



Tipo Option: cuando un valor puede estar ausente



Option<T> es una enumeración (enum) que representa ya sea un valor (Some(T)) o su ausencia (None). Es ideal para situaciones donde no ocurre un error en el sentido clásico, pero el resultado puede estar vacío.



fn encontrar_usuario(id: u32) -> Option<String> {    let base = vec!["Alice".to_string(), "Bob".to_string()];    if id < base.len() {        Some(base[id].clone())    } else {        None    }}

fn main() { match encontrar_usuario(1) { Some(nombre) => println!("Encontrado: {}", nombre), None => println!("Usuario no encontrado"), }}


Tipo Result: éxito o error



Result<T, E> es la herramienta principal para el manejo de errores. También es un enum: Ok(T) (éxito) o Err(E) (error).



use std::fs::File;use std::io::Read;

fn leer_archivo(ruta: &str) -> Result<String, std::io::Error> { let mut archivo = File::open(ruta)?; let mut contenido = String::new(); archivo.read_to_string(&mut contenido)?; Ok(contenido)}


2. Operador ? (signo de interrogación) — reemplazo de try/catch



El operador ? es la forma principal de propagar errores hacia arriba en Rust. Reemplaza las voluminosas construcciones match y hace que el código sea limpio. Si el resultado es Ok, el valor se extrae y se asigna a la variable. Si es Err, la función devuelve inmediatamente ese error.



use std::fs;use std::io;

fn copiar_archivo(origen: &str, destino: &str) -> io::Result<()> { let datos = fs::read(origen)?; // si hay error — salida fs::write(destino, &datos)?; // si hay error — salida Ok(())}

fn main() -> io::Result<()> { copiar_archivo("source.txt", "dest.txt")?; println!("Archivo copiado exitosamente"); Ok(())}


Importante: el operador ? solo funciona en funciones que devuelven Result, Option o tipos que implementan el trait FromResidual.



3. panic!, unwrap y expect — cuando el error es fatal



Macro panic!



panic!() provoca la terminación abrupta del programa (stack unwinding). Se usa solo en situaciones donde continuar la ejecución es imposible o no tiene sentido: errores en la lógica del programa, violación de invariantes, pruebas.



fn division(a: i32, b: i32) -> i32 {    if b == 0 {        panic!("¡División por cero!");    }    a / b}


Métodos unwrap() y expect()



unwrap() es una forma rápida de obtener un valor de Option o Result. Si contiene None o Err — pro

Blogs

Book Recommendations