Lección 26 de 26 Concurrencia y ecosistema
El ecosistema de Rust
- crates.io es el registro de paquetes de Rust. cargo add serde lo apunta en tu Cargo.toml y Cargo lo descarga.
- Cargo trae herramientas oficiales: cargo fmt formatea, cargo clippy te aconseja y cargo doc documenta.
- Con async/.await y Tokio, un solo hilo atiende muchas tareas: mientras una espera a la red, avanza otra.
- Rust está en todas partes: terminal, web, WebAssembly, embebidos y sistemas. ¡Tu próximo proyecto te espera!
Ya conoces el lenguaje: ownership, tipos, traits, iteradores, hilos y tests. Pero programar en Rust en el día a día es también saber moverse por su ecosistema: las librerías de la comunidad, las herramientas que vienen con Cargo y los sitios donde se usa.
Esta lección es de lectura, sin ejercicios. Es un mapa para que sepas qué existe y por dónde seguir cuando termines el curso.
crates.io: el registro de paquetes
crates.io es el registro oficial de crates (paquetes) de Rust, con más de 150 000 publicados. Para añadir uno a tu proyecto usa cargo add:
cargo add serde --features derive
cargo add serde_jsonEl comando escribe las dependencias en tu Cargo.toml, y la próxima vez que compiles Cargo las descargará y compilará por ti:
[dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1""1" significa «cualquier versión 1.x compatible». La versión exacta que se usa queda apuntada en Cargo.lock, así que todo el equipo compila con las mismas.
Cómo elegir un crate
Para casi cualquier problema hay varios crates. Antes de añadir uno, fíjate en:
- Descargas, sobre todo las recientes: indican si la comunidad lo usa de verdad.
- Mantenimiento: fecha de la última versión y si se responden las issues de su repositorio.
- Documentación: cada crate publicado tiene su documentación generada automáticamente en docs.rs. Si tiene ejemplos claros, buena señal.
- Dependencias y licencia: cuantas menos dependencias arrastre, mejor. Y comprueba que la licencia (normalmente MIT o Apache 2.0) encaja con tu proyecto.
Crates imprescindibles
Estos aparecen en casi cualquier proyecto real de Rust:
| Crate | Para qué sirve |
|---|---|
serde y serde_json | Convertir tus structs a JSON, TOML, YAML… y al revés |
tokio | Runtime para código asíncrono: red, temporizadores y miles de tareas |
reqwest | Cliente HTTP para hacer peticiones a APIs |
clap | Leer los argumentos de una aplicación de terminal |
anyhow y thiserror | Errores cómodos: anyhow en aplicaciones, thiserror para definir tus errores en librerías |
rayon | Paralelizar iteradores cambiando iter() por par_iter() |
axum | Framework web para crear APIs y servidores HTTP sobre Tokio |
Con serde, basta un derive para que un struct se pueda leer desde JSON:
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
struct Usuario {
nombre: String,
edad: u8,
}
fn leer_usuario(json: &str) -> serde_json::Result<Usuario> {
serde_json::from_str(json)
}Y con rayon, una cadena de iteradores se reparte entre todos los núcleos del procesador sin escribir un solo hilo:
use rayon::prelude::*;
fn suma_cuadrados(numeros: &[u64]) -> u64 {
numeros.par_iter().map(|n| n * n).sum()
}Las herramientas de Cargo
Rust viene con herramientas oficiales que todo el mundo usa, así que cualquier proyecto se formatea, se revisa y se documenta igual:
| Herramienta | Qué hace |
|---|---|
cargo fmt | Formatea el código con el estilo oficial. Se acabaron las discusiones sobre espacios |
cargo clippy | Linter con cientos de comprobaciones: detecta errores comunes y código mejorable |
cargo doc --open | Genera la documentación de tu proyecto y de sus dependencias y la abre en el navegador |
| rust-analyzer | Extensión para tu editor: autocompletado, tipos en línea y errores mientras escribes |
Clippy es como tener a alguien con experiencia revisando tu código. Con esta función:
fn saludar(nombres: &[&str]) {
if nombres.len() == 0 {
println!("No hay nadie");
}
}Te sugiere una forma más clara:
warning: length comparison to zero
--> src/main.rs:2:8
|
2 | if nombres.len() == 0 {
| ^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `nombres.is_empty()`Consejo: Configura tu editor para ejecutar
cargo fmtal guardar y pasacargo clippyantes de cada commit. Aprenderás muchísimo de sus sugerencias.
Programación asíncrona con async/await y Tokio
Con hilos, cada tarea ocupa un hilo del sistema operativo. Eso funciona con decenas de tareas, pero un servidor que atiende miles de conexiones a la vez, casi todas esperando a la red, necesita algo más ligero. Para eso existe async:
- Una
async fnno se ejecuta al llamarla: devuelve un future, una tarea pendiente. Como los iteradores, es perezosa. .awaitespera a que el future termine sin bloquear el hilo: mientras tanto, el hilo avanza con otras tareas.- El lenguaje define
asyncy.await, pero la biblioteca estándar no incluye el runtime que ejecuta los futures. El más usado es Tokio.
cargo add tokio --features full
cargo add reqwestasync fn tamano(url: &str) -> Result<usize, reqwest::Error> {
let html = reqwest::get(url).await?.text().await?;
Ok(html.len())
}
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
// Las dos descargas avanzan a la vez, sin crear hilos nuevos
let (rust, crates) = tokio::join!(
tamano("https://www.rust-lang.org"),
tamano("https://crates.io"),
);
println!("rust-lang.org: {} bytes", rust?);
println!("crates.io: {} bytes", crates?);
Ok(())
}Este ejemplo necesita las dependencias tokio y reqwest, así que no se puede ejecutar en la web: pruébalo con Cargo en tu ordenador. #[tokio::main] arranca el runtime y tokio::join! espera a varios futures a la vez.
Dónde se usa Rust
- Herramientas de terminal:
ripgrep,batofdsustituyen a clásicos de Unix con más velocidad. Conclapes muy fácil crear las tuyas. - Backend web y servicios de red: Cloudflare, Discord o AWS lo usan donde importan el rendimiento y la fiabilidad. Frameworks como
axumoactix-webte permiten hacer lo mismo. - WebAssembly: Rust compila a WebAssembly para ejecutarse en el navegador a velocidad casi nativa, con herramientas como
wasm-bindgen. - Sistemas embebidos: funciona en microcontroladores sin sistema operativo, gracias a que puede prescindir de la biblioteca estándar (
no_std). - Sistemas: el kernel de Linux, Windows y Android ya incluyen código en Rust.
- Herramientas para JavaScript y Python: SWC, Turbopack, Rolldown (el nuevo bundler de Vite), Biome u Oxc hacen que compilar y analizar JavaScript sea mucho más rápido. En Python,
uvyruffhan seguido el mismo camino.
unsafe: cuando el compilador no puede comprobarlo
Las garantías de Rust se basan en lo que el compilador puede demostrar. Algunas operaciones, como leer un puntero crudo o llamar a una función escrita en C, no se pueden demostrar seguras. Para hacerlas existe el bloque unsafe:
fn main() {
let numero = 42;
let puntero = &numero as *const i32;
// SAFETY: el puntero sale de una referencia a `numero`, que sigue viva.
let valor = unsafe { *puntero };
println!("{valor}");
}unsafe no desactiva el borrow checker ni el resto de comprobaciones. Solo permite unas pocas operaciones extra, como desreferenciar punteros crudos, llamar a funciones unsafe (incluidas las de C) o modificar variables static mut. A cambio, tú garantizas que son correctas.
La biblioteca estándar lo usa por dentro, por ejemplo en Vec, y lo envuelve en APIs seguras. Lo responsable es hacer lo mismo: evitarlo en código de aplicación, mantener los bloques unsafe pequeños y explicar en un comentario // SAFETY: por qué son correctos.
Versiones y ediciones
Rust publica una versión estable nueva cada 6 semanas, sin excepciones. Cada una añade mejoras, pero el código que compila hoy seguirá compilando con las siguientes: es la promesa de estabilidad. Para actualizar:
rustup updateLos cambios que sí podrían romper código llegan en las ediciones, más o menos cada tres años: 2015, 2018, 2021 y 2024, la que usa este curso. Cada crate elige su edición en Cargo.toml:
[package]
name = "mi-proyecto"
version = "0.1.0"
edition = "2024"Crates de ediciones distintas se pueden usar juntos sin problema, y cargo fix --edition migra casi todo automáticamente.
Recursos para seguir aprendiendo
- The Rust Programming Language: «el libro», la guía oficial y gratuita. Es el siguiente paso natural después de este curso.
- Rust by Example: los mismos conceptos explicados con ejemplos ejecutables.
- Rustlings: pequeños ejercicios para arreglar en tu terminal, perfectos para practicar.
- Documentación de la biblioteca estándar: cada tipo y cada método, con ejemplos. Aprende a buscar en ella: la usarás a diario.
Y ahora, a por el certificado
Has recorrido todo el camino: desde tu primer println! hasta hilos, tests y smart pointers. Lo que te diferencia ahora de alguien que programa en Rust a diario es práctica, y la mejor forma de conseguirla es construir algo: una herramienta de terminal, una API pequeña o los ejercicios de Rustlings.
Antes de eso, demuestra lo que has aprendido: aprueba los exámenes de cada sección y consigue tu certificado del curso. Puedes ver qué te falta en tu progreso.
Lección de lectura marcada como completada. Puedes seguir con el siguiente tema.