Principales errores de los desarrolladores principiantes de Rust: de la A a la Z
\n\nRust es un lenguaje de programación potente y seguro, pero su estricto sistema de propiedad y préstamo a menudo desconcierta a los novatos. En este artículo analizaremos los errores más comunes que enfrentan los desarrolladores principiantes en Rust. Cada error va acompañado de un ejemplo de código, una explicación y la solución correcta. ¡Allá vamos!
\n\n1. Ignorar el sistema de propiedad (Ownership)
\n\nEl error más frecuente es intentar usar un valor después de que ha sido movido. En Rust, cada valor solo puede tener un propietario.
\n\n❌ Código erróneo:
\nfn main() {\n let s1 = String::from("hola");\n let s2 = s1;\n println!("{}", s1); // ¡Error! s1 ya no es propietario de la cadena\n}\n\n\n✅ Solución correcta:
\nfn main() {\n let s1 = String::from("hola");\n let s2 = s1.clone(); // Copia explícita\n println!("{}", s1); // Ahora funciona\n println!("{}", s2);\n}\n\n\nConsejo: Use .clone() solo cuando sea realmente necesario. Para tipos primitivos (i32, bool), la copia ocurre automáticamente.
2. Confusión entre String y &str
\n\nLos novatos a menudo no entienden la diferencia entre la cadena con propiedad String y el segmento de cadena &str. Esto provoca errores al pasar cadenas a funciones.
❌ Código erróneo:
\nfn print_message(msg: String) {\n println!("{}", msg);\n}\n\nfn main() {\n let greeting = "Hola"; // &str\n print_message(greeting); // ¡Error! Se espera String\n}\n\n\n✅ Solución correcta:
\nfn print_message(msg: &str) {\n println!("{}", msg);\n}\n\nfn main() {\n let greeting = "Hola";\n print_message(greeting); // ¡Funciona!\n \n let owned = String::from("Mundo");\n print_message(&owned); // &String se convierte automáticamente en &str\n}\n\n\nRegla de oro: En los parámetros de funciones, use &str si no necesita transferir la propiedad de la cadena.
3. Violación de las reglas de préstamo (Borrowing)
\n\nRust no permite tener simultáneamente una referencia mutable y una inmutable al mismo objeto. Esto protege contra condiciones de carrera.
\n\n❌ Código erróneo:
\nfn main() {\n let mut data = vec![1, 2, 3];\n let ref1 = &data;\n let ref2 = &mut data; // ¡Error! Ya existe una referencia inmutable\n println!("{}", ref1);\n}\n\n\n✅ Solución correcta:
\nfn main() {\n let mut data = vec![1, 2, 3];\n {\n let ref1 = &data;\n println!("{}", ref1); // ref1 solo vive en este bloque\n } // ref1 sale del ámbito\n let ref2 = &mut data; // Ahora se puede\n ref2.push(4);\n println!("{:?}", ref2);\n}\n\n\nImportante: El ámbito de una referencia termina en su último uso. El compilador de Rust es lo suficientemente inteligente para rastrearlo.
\n\n4. Problemas con los tiempos de vida (Lifetimes)
\n\nLos errores relacionados con las anotaciones de tiempos de vida son los que más asustan a los novatos. El más típico es devolver una referencia a una variable local.
\n\n❌ Código erróneo:
\nfn get_reference() -> &str {\n let local = String::from("prueba");\n &local // ¡Error! local será destruida al salir de la función\n}\n\n\n✅ Solución correcta (mediante propiedad):
\nfn get_reference() -> String {\n let local = String::from("prueba");\n local // Devolvemos la propiedad\n}\n\nfn main() {\n let s = get_reference();\n println!("{}", s);\n}\n\n\n✅ Solución correcta (mediante parámetro):
\nfn get_reference<'a>(input: &'a str) -> &'a str {\n input // Devolvemos una referencia con el mismo tiempo de vida\n}\n\nfn main() {\n let data = String::from("prueba");\n let result = get_reference(&data);\n println!("{}", result);