Por qué Rust, y lo básico de Cargo
Rust promete seguridad de memoria sin recolector de basura — descubre cómo, y conoce la herramienta que hace que todo proyecto Rust se sienta igual.
Todo programador de sistemas tarde o temprano choca con la misma pared: C y C++ te dan control total sobre la memoria y el hardware, pero ese control viene con minas enterradas — use-after-free, double frees, buffer overflows y data races que solo aparecen bajo carga, meses después de que el código salió a producción. Los lenguajes con recolector de basura, como Java, Go o Python, evitan esos errores gestionando la memoria por ti en tiempo de ejecución, pero lo pagas con pausas del GC, memoria extra y un rendimiento menos predecible — justo lo que no quieres en un módulo de kernel, un motor de videojuego o una base de datos. Durante décadas eso pareció una decisión inevitable: rápido y peligroso, o seguro y más lento.
La apuesta central de Rust es que ese dilema es falso. Su sistema de ownership (propiedad) — que conocerás a fondo en la lección 3 — le permite al compilador rastrear, en tiempo de compilación, exactamente quién es responsable de cada porción de memoria y cuánto tiempo sigue siendo válida. Si tu código liberaría memoria dos veces, la usaría después de que ya no existe, o dejaría que dos hilos modifiquen el mismo dato sin sincronización, Rust simplemente se niega a compilarlo. Nada de esto se verifica en tiempo de ejecución, así que no hay recolector de basura ni penalización de rendimiento — la seguridad está integrada en el propio sistema de tipos.
Por eso se dice que Rust habilita "concurrencia sin miedo" y "refactorización sin miedo": el compilador hace la revisión que haría un ingeniero senior cuidadoso, en cada cambio, antes de que el código llegue a ejecutarse. Por eso también proyectos reales y críticos en rendimiento lo han adoptado — partes del kernel de Linux, el motor de renderizado de Firefox, buena parte del backend de Dropbox, y una porción grande de las nuevas herramientas de línea de comandos y módulos de WebAssembly están escritos en Rust hoy, no como experimento sino porque elimina toda una categoría de incidentes en producción.
Nada de esto importa si las herramientas son incómodas de usar, así que Rust viene con Cargo — su sistema de build, gestor de paquetes, ejecutor de tests y generador de documentación, todo en un solo binario, presente desde tu primer comando. Esto es una ruptura deliberada con C y C++, donde no existe una forma estándar de declarar una dependencia o correr un build; cada proyecto reinventa esa rueda. En Rust, cargo new crea un proyecto funcional y compilable con un solo comando, y cada proyecto Rust que abras — el tuyo o el de alguien más — sigue exactamente la misma estructura.
Ejecutar cargo new hello_rust crea una carpeta con dos cosas importantes: Cargo.toml, el manifiesto donde viven el nombre, la versión y las dependencias de tu paquete (piénsalo como un package.json, pero presente desde el día uno y central para toda la cadena de herramientas), y src/main.rs, donde vive tu código real. Cargo también te deja un programa inicial ya escrito — una función main que imprime "Hello, world!" — así que lo primero que haces con un proyecto Rust nuevo es compilarlo y ejecutarlo con éxito.
Tienes tres comandos para convertir ese código en algo que corre, y elegir el correcto importa a medida que tus proyectos crecen: cargo build compila tu código en un binario dentro de target/debug sin ejecutarlo, cargo run hace eso y además ejecuta el resultado de inmediato, y cargo check se salta por completo la generación de código y el linkeo, preguntando solo "¿esto pasa el chequeo de tipos y el borrow checker?" — lo que lo hace muchísimo más rápido y el comando que vas a usar constantemente mientras iteras, dejando cargo run para cuando realmente quieres ver el programa en acción.
La última pieza del rompecabezas es el propio compilador. Los mensajes de error de Rust son famosos por ser inusualmente útiles: no solo te dicen que una línea está mal, explican por qué en lenguaje claro, señalan el tramo exacto de código responsable y muchas veces sugieren la corrección literal. Al principio vas a apoyarte en el compilador más como maestro que como guardián — lee cada mensaje de error completo antes de empezar a adivinar, porque casi siempre te está diciendo con precisión qué cambiar.
fn main() {println!("Hello, world!");}
This is exactly what cargo new hello_rust writes into src/main.rs for you — a working program before you've typed a single line yourself.
fn main() {let language = "Rust";let year = 2015;println!("{} reached 1.0 in {}.", language, year);}
cargo run compiles and immediately executes this in one step; format arguments inside println! are filled in from left to right by position.
fn greet(name: String) -> String {format!("Hello, {}!", name)}fn main() {let message = greet(String::from("Ferris"));println!("{}", message);}
A function with an explicit parameter and return type, plus a call from main — the same shape you'll use in every Rust program from here on, still using only owned String values.
🧠 Comprueba tu comprensión
0/1 · 0/1 answered1. You're in the middle of writing a function and just want to know if it compiles before you keep going. Why would you reach for cargo check instead of cargo build?