Ir al contenido

Rust vs C++, Go y Python

“¿Aprendo Rust, o Go, o me quedo con Python?” es una de las preguntas más comunes cuando alguien descubre Rust. La respuesta sincera es: depende de lo que quieras construir. Todos los lenguajes de esta página son buenos lenguajes, y los usan millones de personas. Cada uno eligió compromisos distintos.

Piensa en los lenguajes como si fueran vehículos. Un deportivo, una furgoneta de reparto y una bicicleta son todos “buenos”. Simplemente no usarías una bicicleta para hacer una mudanza. Esta página explica esos compromisos con palabras sencillas, para que elijas la herramienta adecuada para tu trabajo. Vamos a intentar ser justos, también con los puntos débiles de Rust.

La gran promesa de Rust es velocidad y seguridad a la vez:

  • Rápido, como C y C++. Rust se compila a código máquina nativo y no tiene recolector de basura (garbage collector), así que no hay pausas mientras se limpia la memoria.
  • Seguro con la memoria sin recolector de basura. Las reglas de ownership (propiedad) y borrowing (préstamo) se comprueban al compilar. Grupos enteros de errores (usar memoria ya liberada, condiciones de carrera entre hilos) se rechazan antes de que el programa llegue a ejecutarse.
  • Herramientas excelentes desde el primer día. Una sola herramienta, Cargo, compila tu código, descarga bibliotecas, ejecuta los tests y genera la documentación. El formateador (rustfmt) y el linter (clippy) son oficiales.
  • Errores del compilador que ayudan. A menudo el compilador te dice exactamente cómo arreglar el problema.

Y parece que a quienes lo usan les gusta: en la encuesta de desarrolladores de Stack Overflow de 2025 (en inglés), Rust volvió a ser el lenguaje “más admirado”, es decir, la mayoría de las personas que lo usan quieren seguir usándolo.

Empecemos con algo pequeño: sumar los números pares de una lista. Así queda en Rust:

fn main() {
let numbers = vec![1, 2, 3, 4, 5, 6];
let sum: i32 = numbers.iter().filter(|n| *n % 2 == 0).sum();
println!("Suma de los números pares: {sum}");
}

Salida:

Suma de los números pares: 12
▶ Pruébalo tú mismo

El mismo programa en C++:

#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5, 6};
int sum = 0;
for (int n : numbers) {
if (n % 2 == 0) {
sum += n;
}
}
std::cout << "Suma de los números pares: " << sum << "\n";
}

En Go:

package main
import "fmt"
func main() {
numbers := []int{1, 2, 3, 4, 5, 6}
sum := 0
for _, n := range numbers {
if n%2 == 0 {
sum += n
}
}
fmt.Println("Suma de los números pares:", sum)
}

Y en Python:

numbers = [1, 2, 3, 4, 5, 6]
total = sum(n for n in numbers if n % 2 == 0)
print("Suma de los números pares:", total)

Los cuatro imprimen la misma línea. Python es el más corto, Go y C++ usan un bucle normal, y Rust usa una cadena de iteradores con una closure (una función anónima). En Rust también podrías escribir un bucle for. En programas pequeños como este, las diferencias son sobre todo de estilo. Las diferencias de verdad aparecen en programas más grandes.

C++ y Rust apuntan al mismo terreno: programas rápidos con control total sobre la memoria, como navegadores, motores de videojuegos, bases de datos y sistemas operativos. La gran diferencia es quién comprueba que la memoria se usa correctamente.

En C++, eres tú. Aquí tienes un error clásico. Un compilador de C++ acepta este código sin quejarse, pero push_back puede mover el vector a otra zona de memoria, así que first puede quedar apuntando a memoria que ya se liberó:

std::vector<int> v = {1, 2, 3};
int& first = v[0];
v.push_back(4); // puede mover la memoria del vector...
std::cout << first << "\n"; // ...así que esto puede leer memoria liberada

El mismo error en Rust no compila:

fn main() {
let mut v = vec![1, 2, 3];
let first = &v[0];
v.push(4);
println!("{first}");
}
error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
--> src/main.rs:4:5
|
3 | let first = &v[0];
| - immutable borrow occurs here
4 | v.push(4);
| ^^^^^^^^^ mutable borrow occurs here
5 | println!("{first}");
| ----- immutable borrow later used here

El compilador dice: no se puede tomar prestado v como mutable porque también está prestado como inmutable. Las marcas señalan dónde empieza el préstamo inmutable (&v[0]), dónde se intenta el préstamo mutable (v.push(4)) y dónde se vuelve a usar el primero (println!).

Esto importa mucho en la práctica. El equipo de Chromium informa de que alrededor del 70 % de sus errores de seguridad graves son problemas de seguridad de memoria (en inglés). El equipo de Android de Google lleva varios años escribiendo código nuevo en Rust. En 2022 informaron de cero vulnerabilidades de seguridad de memoria encontradas en el código Rust de Android (en inglés), y en 2025, de una densidad de vulnerabilidades de memoria más de 1000 veces menor que en su código C y C++ (en inglés). El kernel de Linux también admite código escrito en Rust.

Herramientas: C++ tiene muchos sistemas de compilación y gestores de paquetes, y los equipos suelen dedicar bastante tiempo a la configuración. Rust tiene una herramienta estándar, Cargo, así que todos los proyectos de Rust se compilan de la misma manera.

Curva de aprendizaje: los dos son difíciles. C++ es enorme, y muchas de sus reglas se aprenden cometiendo errores en tiempo de ejecución. Las reglas de Rust son estrictas, pero el compilador las hace cumplir y las explica, así que las aprendes en tiempo de compilación.

Dónde C++ sigue ganando: décadas de código existente, bibliotecas y desarrolladores con experiencia. Si tu empresa o tu motor de videojuegos se basa en C++, C++ suele ser la opción práctica. Rust puede llamar a código C, y a C++ a través de interfaces de estilo C, pero mezclarlos cuesta trabajo.

Go y Rust se comparan a menudo porque los dos son modernos, compilados y populares para servidores y herramientas de línea de comandos. Pero se diseñaron con objetivos distintos.

Recolector de basura vs ownership. Go usa un recolector de basura (en inglés) que encuentra y libera la memoria que ya no se usa mientras tu programa corre. Eso hace que el código Go sea más sencillo de escribir: nunca piensas en quién es el dueño de un valor. El precio es algo de memoria y CPU extra, y pausas cortas. Rust no tiene recolector de basura. La memoria se libera en un momento conocido, cuando el dueño sale de su ámbito (scope). Eso da un rendimiento más predecible, pero tienes que aprender ownership y borrowing.

Concurrencia. Las goroutines y los canales de Go son famosos por lo fáciles que son. Aquí tienes un pequeño ejemplo que eleva al cuadrado tres números en paralelo y los suma:

results := make(chan int)
for n := 1; n <= 3; n++ {
go func() {
results <- n * n
}()
}
total := 0
for i := 0; i < 3; i++ {
total += <-results
}
fmt.Println("total:", total)

La versión en Rust usa hilos y un canal (channel). Es un poco más larga: clonas el emisor para cada hilo y usas move:

use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
for n in 1..=3 {
let tx = tx.clone();
thread::spawn(move || {
tx.send(n * n).unwrap();
});
}
drop(tx); // cerramos nuestra copia para que el bucle de abajo pueda terminar
let total: i32 = rx.iter().sum();
println!("total: {total}");
}

Salida:

total: 14
▶ Pruébalo tú mismo

Lo que obtienes a cambio de escribir un poco más: Rust se niega a compilar código en el que dos hilos podrían modificar los mismos datos a la vez (una condición de carrera, o data race). En Go las condiciones de carrera son posibles; Go ofrece un detector de carreras (en inglés) que las encuentra mientras el programa corre. Mira Concurrencia para saber más.

Tiempos de compilación. Go se creó para compilar rápido. Sus preguntas frecuentes dicen que compilar un ejecutable grande debería tardar como mucho unos pocos segundos (en inglés). Rust compila más despacio, porque el compilador hace muchas más comprobaciones y optimizaciones. Lo vas a notar en proyectos grandes.

Sencillez. Go es un lenguaje pequeño a propósito, con pocas características que aprender, así que mucha gente siente que puede leer código Go rápidamente. Rust tiene más características (traits, genéricos, lifetimes, macros), que dan más poder pero llevan más tiempo de aprender.

Python y Rust son muy distintos, y a menudo se usan juntos en lugar de uno en vez del otro.

Velocidad. Python es interpretado, así que el código Python puro que hace muchos cálculos es mucho más lento que el código compilado. Por eso las bibliotecas populares de Python suelen hacer el trabajo pesado en C, C++ o Rust por debajo.

Tipos. En Python, los tipos se comprueban mientras el programa se ejecuta. Esta función funciona con un número y falla con una cadena de texto, pero solo te enteras cuando se ejecuta esa línea:

def add_tax(price):
return price * 1.2
print(add_tax(10)) # 12.0
print(add_tax("10")) # TypeError: can't multiply sequence by non-int of type 'float'

Python tiene anotaciones de tipo opcionales (type hints), pero el intérprete de Python no las hace cumplir. En Rust, todos los tipos se comprueban antes de que el programa se ejecute:

fn add_tax(price: f64) -> f64 {
price * 1.2
}
fn main() {
println!("{}", add_tax(10.0));
println!("{}", add_tax("10"));
}
error[E0308]: mismatched types
--> src/main.rs:7:28
|
7 | println!("{}", add_tax("10"));
| ------- ^^^^ expected `f64`, found `&str`
| |
| arguments to this function are incorrect

El compilador avisa de que los tipos no coinciden: la función esperaba un f64 y recibió un &str, así que los argumentos de la llamada son incorrectos.

Cuándo Python sigue siendo la mejor herramienta: scripts rápidos, análisis de datos, machine learning, notebooks, automatización y enseñar a principiantes. El ecosistema de Python para ciencia de datos es enorme, y puedes probar una idea en minutos. Si tu programa pasa la mayor parte del tiempo esperando a la red o a una base de datos, la velocidad de Python muchas veces no importa.

Usar los dos: el proyecto PyO3 (en inglés) te permite escribir módulos de Python en Rust, así que puedes conservar tu código Python y pasar a Rust solo la parte lenta. Algunas herramientas populares de Python están escritas en Rust; por ejemplo, la encuesta de Stack Overflow señala que el gestor de paquetes de Python uv está hecho en Rust (en inglés).

Son tendencias generales, no reglas estrictas. Un programa bien escrito en cualquiera de estos lenguajes puede ser “lo bastante rápido”.

Rust C++ Go Python
Velocidad Muy rápido, código nativo, sin GC Muy rápido, código nativo, sin GC Rápido, código nativo con GC Más lento en cálculos pesados con Python puro
Seguridad de memoria Comprobada al compilar (fuera de unsafe) Responsabilidad del programador GC; las condiciones de carrera siguen siendo posibles GC; segura, pero los errores de tipo aparecen al ejecutar
Curva de aprendizaje Empinada al principio Empinada, y un lenguaje muy grande Suave La más suave
Tiempo de compilación Algo lento Algo lento (depende del proyecto) Muy rápido No hay paso de compilación
Ecosistema Más joven, en crecimiento; Cargo incluido Enorme y maduro; muchas herramientas de compilación Biblioteca estándar sólida, ideal para servidores Enorme, sobre todo en datos y ML
Usos típicos Herramientas CLI, servidores, código de sistemas, WebAssembly, embebidos Videojuegos, navegadores, sistemas de alto rendimiento y heredados Servicios web, herramientas de nube y DevOps Scripts, ciencia de datos, ML, automatización

(GC = recolector de basura, garbage collector).

Hazte estas preguntas:

  • ¿Necesitas la máxima velocidad o poco consumo de memoria, por ejemplo para un motor de videojuegos, una base de datos o código en un dispositivo pequeño? Rust (o C++) es una opción sólida.
  • ¿Los errores van a salir caros? El código sensible a la seguridad, los servidores que corren durante mucho tiempo y el código del que dependen muchas personas son los que más ganan con las comprobaciones de Rust al compilar.
  • ¿Estás creando una herramienta de línea de comandos que quieres compartir? Rust genera un único binario rápido, sin runtime que instalar. Go también es excelente para esto.
  • ¿Necesitas un servicio web rápido, con un equipo que no conoce ninguno de estos lenguajes? Probablemente Go te lleve ahí antes. Rust también funciona bien (mira el Proyecto: API web), pero el tiempo de aprendizaje es mayor.
  • ¿Es un script rápido, un análisis de datos o un experimento de ML? Usa Python. Recurre a Rust más adelante, mediante PyO3, si alguna parte se vuelve demasiado lenta.
  • ¿Hay una gran base de código en C++? Quédate con C++ por ahora, o introduce Rust en partes nuevas y separadas, como hizo Android.

Y si simplemente quieres programar mejor: aprender Rust te enseña cómo funciona de verdad la memoria, y ese conocimiento te sirve en cualquier otro lenguaje.

Rust no es perfecto. Estas son las cosas que más le cuestan a la gente:

  • La curva de aprendizaje es real. Las primeras semanas con el borrow checker (el verificador de préstamos) pueden ser frustrantes. Cuenta con “pelearte con el compilador” durante un tiempo. Todo se vuelve mucho más fácil cuando el ownership encaja.
  • Los tiempos de compilación son más lentos que los de Go, sobre todo en proyectos grandes y en compilaciones de release.
  • Algunas cosas son más difíciles de expresar. Los datos con forma de grafo, con muchos enlaces entre objetos, o el código que comparte mucho estado mutable, necesitan herramientas como los smart pointers (punteros inteligentes) y requieren más planificación.
  • El ecosistema es más joven. En algunas áreas (aplicaciones con interfaz gráfica, ciertas bibliotecas científicas) hay menos opciones maduras que en C++ o Python.
  • Lo usa menos gente (por ahora). En la encuesta de Stack Overflow de 2025 (en inglés), muchas más personas dijeron usar Python (alrededor del 58 %) o C++ (alrededor del 24 %) que Rust (alrededor del 15 %). Eso significa menos desarrolladores de Rust con experiencia a quienes contratar, preguntar o de quienes aprender en el trabajo.
  • Más código para cosas sencillas. Como mostró el ejemplo de los canales, Rust a menudo te pide ser explícito donde otros lenguajes son más relajados.
  • Rust da una velocidad al nivel de C++ con seguridad de memoria comprobada al compilar, y trae herramientas excelentes incluidas.
  • Frente a C++, Rust evita categorías enteras de errores de memoria antes de que el programa se ejecute; C++ tiene muchísimo más código y bibliotecas existentes.
  • Frente a Go, Rust no tiene recolector de basura y detiene las condiciones de carrera al compilar; Go es más sencillo y compila mucho más rápido.
  • Frente a Python, Rust es mucho más rápido y comprueba los tipos antes de ejecutar; Python se escribe más rápido y domina la ciencia de datos. PyO3 te permite combinarlos.
  • Los principales costes de Rust son una curva de aprendizaje empinada, compilaciones más lentas y un ecosistema más joven.

Comprueba lo aprendido

1. ¿Cómo gestiona Rust la memoria sin un recolector de basura?

2. ¿Cuál de estas es una ventaja real de Go frente a Rust?

3. Tienes un programa en Python en el que una función es demasiado lenta. ¿Qué se suele hacer?

4. En el ejemplo de C++ frente a Rust, ¿qué pasa con el código que guarda &v[0] y luego hace push sobre v?

Puntuación: 0 / 4