Rust
Tutorial Rust: Primer programa
Aprende a crear y ejecutar tu primer programa en Rust con Cargo, gestionando proyectos y compilación paso a paso.
Aprende Rust y certifícateEstructura Cargo
Cuando trabajamos con Rust, utilizamos Cargo como el sistema de gestión de paquetes y herramienta de construcción oficial. Cargo se encarga de muchas tareas esenciales como descargar dependencias, compilar el código y generar ejecutables.
Al crear un nuevo proyecto con Cargo, se genera automáticamente una estructura de directorios específica que sigue convenciones estándar. Esta organización facilita el desarrollo y mantenimiento de proyectos Rust.
Para crear un nuevo proyecto, abrimos una terminal y ejecutamos:
cargo new mi_proyecto
Este comando genera un nuevo directorio llamado mi_proyecto
con la siguiente estructura:
mi_proyecto/
├── Cargo.toml
└── src/
└── main.rs
Vamos a examinar cada elemento de esta estructura:
Directorio raíz del proyecto
El directorio raíz (en este caso mi_proyecto
) contiene todos los archivos y carpetas relacionados con nuestro proyecto. Este es el espacio de trabajo principal donde Cargo buscará la configuración y los archivos fuente.
Archivo Cargo.toml
El archivo Cargo.toml
es el manifiesto del proyecto y contiene la configuración y metadatos necesarios. TOML (Tom's Obvious, Minimal Language) es un formato de configuración simple y legible. Veamos un ejemplo básico:
[package]
name = "mi_proyecto"
version = "0.1.0"
edition = "2021"
[dependencies]
Las secciones principales son:
[package]: Contiene la información básica del proyecto:
name
: El nombre del proyectoversion
: La versión actual siguiendo el formato de versionado semánticoedition
: La edición de Rust que se utilizará (2015, 2018 o 2021)[dependencies]: Aquí se declaran las bibliotecas externas (crates) que nuestro proyecto utilizará. Inicialmente está vacía.
Directorio src/
El directorio src/
(source) es donde se almacena todo el código fuente de nuestro proyecto. Cargo espera encontrar aquí los archivos .rs
que contienen nuestro código Rust.
Archivo main.rs
Para un proyecto ejecutable (en contraposición a una biblioteca), Cargo crea automáticamente el archivo src/main.rs
. Este archivo contiene el punto de entrada de nuestro programa, la función main()
.
Otros archivos generados
Cuando compilamos nuestro proyecto, Cargo genera automáticamente algunos archivos y directorios adicionales:
target/: Directorio donde se almacenan los resultados de la compilación. Contiene:
Archivos objeto intermedios
Ejecutables finales
Documentación generada
Cargo.lock: Este archivo se genera automáticamente después de la primera compilación y registra las versiones exactas de todas las dependencias. Esto garantiza compilaciones reproducibles.
Estructura para proyectos más complejos
A medida que nuestro proyecto crece, podemos añadir más elementos a esta estructura básica:
- tests/: Directorio para pruebas de integración
- examples/: Ejemplos de uso de nuestra biblioteca
- benches/: Pruebas de rendimiento
- src/bin/: Múltiples ejecutables dentro del mismo proyecto
Para proyectos iniciales, la estructura básica es suficiente y nos permite concentrarnos en aprender el lenguaje sin preocuparnos por la organización de archivos.
Convenciones de nombres
Cargo sigue algunas convenciones importantes:
- Los nombres de proyectos usan guiones (
mi-proyecto
) enCargo.toml
- Los nombres de paquetes en el código Rust usan guiones bajos (
mi_proyecto
) - Los archivos de código usan snake_case (
mi_archivo.rs
)
Estas convenciones ayudan a mantener la consistencia entre proyectos Rust y facilitan la colaboración entre desarrolladores.
main.rs básico
Ahora que entendemos la estructura de un proyecto Rust, vamos a examinar el archivo main.rs
que Cargo ha generado automáticamente. Este archivo contiene el código inicial de nuestro programa y es el punto de partida para cualquier aplicación Rust.
Al abrir el archivo src/main.rs
con tu editor de código favorito, encontrarás el siguiente contenido:
fn main() {
println!("Hello, world!");
}
Aunque parece simple, este pequeño programa contiene varios elementos fundamentales de Rust que debemos entender:
Función main
La línea fn main() {
define la función principal de nuestro programa:
fn main() {
// Código de la función
}
fn
es la palabra clave que indica que estamos definiendo una funciónmain
es el nombre de la función - esta función específica es especial()
indica que la función no recibe parámetros{ }
son las llaves que delimitan el cuerpo de la función
La función main
es el punto de entrada de cualquier programa ejecutable en Rust. Cuando ejecutamos nuestro programa, el sistema operativo comienza la ejecución desde esta función. Sin una función main
, no tendríamos un programa ejecutable.
Instrucción println!
Dentro de la función main, encontramos esta línea:
println!("Hello, world!");
Esta instrucción muestra texto en la consola:
println!
es una macro de Rust (no una función normal)- Las macros en Rust se identifican por el signo de exclamación
!
"Hello, world!"
es una cadena de texto literal (string)- La instrucción termina con
;
(punto y coma), que marca el final de la expresión
¿Qué es una macro?
Las macros en Rust son diferentes de las funciones normales. Una macro es un tipo de código que escribe otro código (metaprogramación). No necesitas entender completamente las macros ahora, pero es importante saber que println!
es una macro que facilita la impresión de texto formateado en la consola.
Modificando nuestro primer programa
Podemos modificar este programa básico para que muestre un mensaje personalizado. Por ejemplo:
fn main() {
println!("¡Mi primer programa en Rust!");
}
También podemos añadir más llamadas a println!
para mostrar múltiples líneas:
fn main() {
println!("¡Mi primer programa en Rust!");
println!("Estoy aprendiendo un nuevo lenguaje.");
}
Imprimiendo valores variables
La macro println!
puede hacer más que simplemente imprimir texto estático. También puede formatear e imprimir valores:
fn main() {
let lenguaje = "Rust";
let año = 2023;
println!("Estoy aprendiendo {} en {}.", lenguaje, año);
}
En este ejemplo:
let lenguaje = "Rust";
crea una variable llamadalenguaje
con el valor "Rust"let año = 2023;
crea otra variable llamadaaño
con el valor numérico 2023- Las llaves
{}
dentro del string son marcadores de posición que serán reemplazados por los valores de las variables
Comentarios en Rust
Es una buena práctica añadir comentarios a tu código para explicar lo que hace. En Rust, los comentarios se escriben así:
fn main() {
// Esto es un comentario de una línea
/* Esto es un comentario
que abarca múltiples
líneas */
println!("¡Hola desde Rust!"); // Los comentarios pueden ir al final de una línea
}
Los comentarios son ignorados por el compilador y sirven como notas para los programadores.
Estructura básica completa
Juntando todo lo que hemos visto, un archivo main.rs
básico pero completo podría verse así:
// Mi primer programa en Rust
fn main() {
// Definimos algunas variables
let nombre = "Programador";
let lenguaje = "Rust";
// Imprimimos mensajes en la consola
println!("¡Hola, {}!", nombre);
println!("Bienvenido al mundo de {}.", lenguaje);
println!("Este es tu primer programa.");
}
Este programa muestra tres líneas de texto en la consola, incluyendo valores de variables. Es simple pero ilustra los conceptos básicos de un programa Rust.
Recuerda que cada instrucción en Rust termina con un punto y coma (;
), excepto cuando la última expresión de un bloque es el valor de retorno de ese bloque (algo que veremos más adelante).
Build y ejecución
Una vez que hemos creado nuestro proyecto y entendido la estructura básica del archivo main.rs
, el siguiente paso es compilar y ejecutar nuestro programa. Cargo nos proporciona varias herramientas para facilitar este proceso.
El ciclo de desarrollo en Rust
El ciclo de desarrollo típico en Rust sigue estos pasos:
- Escribir o modificar el código
- Comprobar que el código no tiene errores
- Compilar el código en un ejecutable
- Ejecutar el programa
- Repetir
Cargo nos ofrece comandos específicos para cada una de estas etapas, lo que simplifica enormemente nuestro flujo de trabajo.
Verificación del código con cargo check
Antes de compilar completamente nuestro programa, podemos usar cargo check
para verificar rápidamente si nuestro código tiene errores:
cargo check
Este comando analiza nuestro código sin generar un ejecutable, lo que lo hace mucho más rápido que una compilación completa. Es ideal para comprobar errores de sintaxis o problemas de tipado mientras estamos escribiendo código.
Si nuestro código no tiene errores, veremos un mensaje como:
Checking mi_proyecto v0.1.0
Finished dev [unoptimized + debuginfo] target(s) in 0.15s
Si hay errores, Cargo nos mostrará mensajes detallados indicando dónde están los problemas y sugerencias para solucionarlos.
Compilación con cargo build
Para compilar nuestro programa y generar un ejecutable, usamos:
cargo build
Este comando compila nuestro código y crea un ejecutable en el directorio target/debug/
. Por defecto, Cargo compila en modo de desarrollo, que incluye información de depuración pero no está optimizado para rendimiento.
Si la compilación es exitosa, veremos algo como:
Compiling mi_proyecto v0.1.0
Finished dev [unoptimized + debuginfo] target(s) in 0.72s
El ejecutable generado se encuentra en target/debug/mi_proyecto
(o target\debug\mi_proyecto.exe
en Windows).
Compilación para producción
Cuando nuestro programa está listo para ser distribuido, podemos compilarlo con optimizaciones usando la bandera --release
:
cargo build --release
Este comando genera un ejecutable optimizado en target/release/
que es más rápido pero tarda más en compilarse y no incluye información de depuración:
Compiling mi_proyecto v0.1.0
Finished release [optimized] target(s) in 1.21s
Ejecución del programa
Hay dos formas principales de ejecutar nuestro programa:
- Ejecutar directamente el archivo compilado:
# En sistemas Unix/Linux/macOS
./target/debug/mi_proyecto
# En Windows
.\target\debug\mi_proyecto.exe
- Usar el comando cargo run:
cargo run
El comando cargo run
es especialmente útil porque compila y ejecuta nuestro programa en un solo paso. Si el código ha cambiado desde la última compilación, Cargo lo recompilará automáticamente antes de ejecutarlo.
Si queremos ejecutar la versión optimizada:
cargo run --release
Ejemplo práctico
Veamos un ejemplo completo del flujo de trabajo:
- Modificamos nuestro programa en
src/main.rs
:
fn main() {
let mensaje = "¡Hola desde Rust!";
println!("{}", mensaje);
println!("Este es mi primer programa compilado y ejecutado.");
}
- Verificamos que no hay errores:
cargo check
- Compilamos y ejecutamos en un solo paso:
cargo run
Veremos una salida similar a esta:
Compiling mi_proyecto v0.1.0
Finished dev [unoptimized + debuginfo] target(s) in 0.42s
Running `target/debug/mi_proyecto`
¡Hola desde Rust!
Este es mi primer programa compilado y ejecutado.
Limpieza del proyecto
Con el tiempo, el directorio target/
puede crecer considerablemente. Para eliminar todos los archivos compilados y empezar desde cero:
cargo clean
Este comando elimina todo el directorio target/
, liberando espacio en disco.
Mensajes de error
Una de las características más destacadas de Rust es la calidad de sus mensajes de error. Si cometemos un error en nuestro código, Cargo nos proporcionará información detallada y útil.
Por ejemplo, si olvidamos un punto y coma:
fn main() {
let mensaje = "¡Hola desde Rust!" // Falta el punto y coma
println!("{}", mensaje);
}
Al ejecutar cargo check
o cargo build
, veremos un mensaje de error claro:
error: expected `;`, found `println`
--> src/main.rs:3:5
|
2 | let mensaje = "¡Hola desde Rust!"
| ^ help: add `;` here
3 | println!("{}", mensaje);
| ^^^^^^^ unexpected token
Estos mensajes no solo indican dónde está el error, sino que también sugieren cómo solucionarlo.
Resumen del flujo de trabajo
Para un desarrollo eficiente en Rust, podemos seguir este flujo de trabajo:
- Usar
cargo check
frecuentemente mientras escribimos código para detectar errores rápidamente - Usar
cargo run
para probar nuestro programa durante el desarrollo - Usar
cargo build --release
cuando estemos listos para crear la versión final optimizada
Este ciclo de desarrollo nos permite trabajar de manera eficiente y aprovechar al máximo las herramientas que Cargo nos proporciona.
Otras lecciones de Rust
Accede a todas las lecciones de Rust y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Rust
Introducción Y Entorno
Primer Programa
Introducción Y Entorno
Instalación Del Entorno
Introducción Y Entorno
Funciones
Sintaxis
Operadores
Sintaxis
Estructuras De Control Condicional
Sintaxis
Arrays Y Strings
Sintaxis
Manejo De Errores Panic
Sintaxis
Variables Y Tipos Básicos
Sintaxis
Estructuras De Control Iterativo
Sintaxis
Colecciones Estándar
Estructuras De Datos
Option Y Result
Estructuras De Datos
Pattern Matching
Estructuras De Datos
Estructuras (Structs)
Estructuras De Datos
Enumeraciones Enums
Estructuras De Datos
El Concepto De Ownership
Ownership
Lifetimes Básicos
Ownership
Slices Y Referencias Parciales
Ownership
References Y Borrowing
Ownership
Funciones Anónimas Closures
Abstracción
Traits De La Biblioteca Estándar
Abstracción
Traits
Abstracción
Generics
Abstracción
Channels Y Paso De Mensajes
Concurrencia
Memoria Compartida Segura
Concurrencia
Threads Y Sincronización Básica
Concurrencia
Introducción A Tokio
Asincronía
Fundamentos Asíncronos Y Futures
Asincronía
Async/await
Asincronía
Ejercicios de programación de Rust
Evalúa tus conocimientos de esta lección Primer programa con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender la estructura básica de un proyecto Rust generado por Cargo.
- Identificar los archivos y directorios principales como Cargo.toml, src/main.rs y target/.
- Entender la función main y la macro println! para imprimir en consola.
- Aprender a compilar, verificar y ejecutar programas Rust usando comandos Cargo.
- Interpretar mensajes de error comunes y aplicar buenas prácticas como el uso de comentarios.