Rust: Programación de Sistemas Segura

Aprende Rust, el lenguaje que garantiza seguridad de memoria sin garbage collector


Rust: Programación de Sistemas Segura
1 Cargando...

Rust: Programación de Sistemas Segura

Rust es un lenguaje de programación de sistemas que combina rendimiento de bajo nivel con garantías de seguridad en tiempo de compilación. Creado por Mozilla y lanzado en 2010, Rust elimina clases enteras de bugs relacionados con la memoria a través de su sistema único de ownership, sin sacrificar el rendimiento.

¿Por qué Rust? Rust ha sido votado como el “lenguaje más amado” en el Stack Overflow Survey durante 8 años consecutivos. Empresas como Microsoft, Google, Amazon y Discord usan Rust en producción.

Conceptos Fundamentales

Ownership, Borrowing y Lifetimes

El sistema de ownership es el corazón de Rust:

// Ownership - cada valor tiene un único dueño
fn main() {
    let s1 = String::from("hello");
    let s2 = s1; // s1 se mueve a s2
    // println!("{}", s1); // ¡ERROR! s1 ya no es válido
    println!("{}", s2); // OK
}

// Borrowing - referencias inmutables
fn calcular_longitud(s: &String) -> usize {
    s.len()
}

// Borrowing mutable
fn agregar_texto(s: &mut String) {
    s.push_str(" world");
}

fn main() {
    let mut texto = String::from("hello");
    
    // Múltiples referencias inmutables están permitidas
    let r1 = &texto;
    let r2 = &texto;
    println!("{} y {}", r1, r2);
    
    // Solo UNA referencia mutable a la vez
    let r3 = &mut texto;
    r3.push_str("!");
    println!("{}", r3);
}

// Lifetimes - garantizan que las referencias sean válidas
fn mayor<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() { x } else { y }
}

Tipos de Datos

// Tipos primitivos
let entero: i32 = 42;
let flotante: f64 = 3.14;
let booleano: bool = true;
let caracter: char = '🦀';

// Tuplas
let tupla: (i32, f64, &str) = (42, 3.14, "rust");
let (x, y, z) = tupla; // Destructuring

// Arrays (tamaño fijo)
let array: [i32; 5] = [1, 2, 3, 4, 5];
let primero = array[0];

// Vectores (tamaño dinámico)
let mut vec: Vec<i32> = vec![1, 2, 3];
vec.push(4);

// Strings
let s1: &str = "string literal"; // String slice
let s2: String = String::from("owned string");

// HashMap
use std::collections::HashMap;
let mut mapa: HashMap<&str, i32> = HashMap::new();
mapa.insert("clave", 42);

Structs y Enums

// Struct
#[derive(Debug, Clone)]
struct Usuario {
    nombre: String,
    email: String,
    edad: u32,
    activo: bool,
}

impl Usuario {
    // Constructor
    fn nuevo(nombre: String, email: String, edad: u32) -> Self {
        Self {
            nombre,
            email,
            edad,
            activo: true,
        }
    }
    
    // Método
    fn saludar(&self) -> String {
        format!("¡Hola, {}!", self.nombre)
    }
    
    // Método mutable
    fn desactivar(&mut self) {
        self.activo = false;
    }
}

// Enum con datos
enum Mensaje {
    Salir,
    Mover { x: i32, y: i32 },
    Escribir(String),
    CambiarColor(u8, u8, u8),
}

// Pattern matching
fn procesar_mensaje(msg: Mensaje) {
    match msg {
        Mensaje::Salir => println!("Saliendo..."),
        Mensaje::Mover { x, y } => println!("Moviendo a ({}, {})", x, y),
        Mensaje::Escribir(texto) => println!("Texto: {}", texto),
        Mensaje::CambiarColor(r, g, b) => println!("Color: RGB({}, {}, {})", r, g, b),
    }
}

// Option y Result
fn dividir(a: f64, b: f64) -> Option<f64> {
    if b == 0.0 { None } else { Some(a / b) }
}

fn leer_archivo(ruta: &str) -> Result<String, std::io::Error> {
    std::fs::read_to_string(ruta)
}

Traits

// Definiendo un trait
trait Resumible {
    fn resumen(&self) -> String;
    
    // Implementación por defecto
    fn descripcion(&self) -> String {
        format!("Resumen: {}", self.resumen())
    }
}

// Implementando trait
struct Articulo {
    titulo: String,
    autor: String,
    contenido: String,
}

impl Resumible for Articulo {
    fn resumen(&self) -> String {
        format!("{} por {}", self.titulo, self.autor)
    }
}

// Trait bounds en generics
fn imprimir_resumen<T: Resumible>(item: &T) {
    println!("{}", item.resumen());
}

Concurrencia

use std::thread;
use std::sync::{Arc, Mutex};

// Threads básicos
fn main() {
    let handle = thread::spawn(|| {
        for i in 1..10 {
            println!("Thread: {}", i);
        }
    });
    
    for i in 1..5 {
        println!("Main: {}", i);
    }
    
    handle.join().unwrap();
}

// Compartiendo datos entre threads
fn contador_compartido() {
    let contador = Arc::new(Mutex::new(0));
    let mut handles = vec![];
    
    for _ in 0..10 {
        let contador = Arc::clone(&contador);
        let handle = thread::spawn(move || {
            let mut num = contador.lock().unwrap();
            *num += 1;
        });
        handles.push(handle);
    }
    
    for handle in handles {
        handle.join().unwrap();
    }
    
    println!("Resultado: {}", *contador.lock().unwrap());
}

Herramientas del Ecosistema

HerramientaPropósito
cargoGestor de paquetes y build
rustfmtFormateador de código
clippyLinter con consejos avanzados
rust-analyzerLSP para IDEs

Lista de Verificación de Aprendizaje

  • Entender ownership, borrowing y lifetimes
  • Dominar structs, enums y pattern matching
  • Aprender traits y generics
  • Estudiar manejo de errores con Result y Option
  • Explorar concurrencia y async/await
  • Construir un proyecto CLI
  • Contribuir a proyectos Rust open source

Recursos Esenciales

Cita

“Rust es un lenguaje que respeta el tiempo y la inteligencia del desarrollador.” - Steve Klabnik


¡Rust puede parecer desafiante al principio, pero las garantías de seguridad que ofrece valen la inversión!