Variables globales en Rust: mitos, realidad y alternativas seguras

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: "¿Y dónde están las variables globales?" — el primer shock del principiante en Rust

\n\n

Acabas de empezar a estudiar Rust, escribiste un par de programas y de repente te das cuenta: necesitas que alguna variable sea accesible desde cualquier punto del código. En Python o JavaScript simplemente escribirías global_var = 42 en el nivel superior y listo. Pero en Rust... el compilador te mira con reproche y te da un error.

\n\n

La pregunta "Is it possible to use global variables in Rust?" es una de las más populares en Stack Overflow. Y con razón. Rust, a diferencia de muchos lenguajes, no permite simplemente declarar una variable global. ¿Por qué? Porque la seguridad de memoria no es solo una palabra de moda, sino la base del lenguaje.

\n\n

En este artículo analizaremos todas las formas de trabajar con datos globales en Rust: desde constantes simples hasta almacenes seguros para hilos. Aprenderás cómo sortear las limitaciones del compilador sin sacrificar la seguridad, y cuándo las variables globales son un mal y cuándo una necesidad.

\n\n

¿Por qué Rust prohíbe las variables globales "normales"?

\n\n

Antes de buscar soluciones, entendamos el problema. En Rust rigen reglas estrictas de propiedad (ownership) y préstamo (borrowing). Una variable global que puede ser modificada desde cualquier hilo en cualquier momento es un camino directo a una condición de carrera (data race).

\n\n

Imagina: dos hilos intentan escribir diferentes valores en la misma variable global al mismo tiempo. El resultado es impredecible. En C++ o C esto lleva a un comportamiento indefinido. Rust garantiza que esto simplemente no se compilará.

\n\n

Por lo tanto, el compilador nos exige especificar explícitamente:

\n
    \n
  • ¿La variable es inmutable? Usa const o static.
  • \n
  • ¿La variable es mutable y se usa en un solo hilo? Usa static mut (con unsafe).
  • \n
  • ¿La variable es mutable y se usa en varios hilos? Usa Mutex, RwLock o tipos atómicos.
  • \n
\n\n

Método 1: Constantes (const) — la opción más segura

\n\n

Si tu "valor global" es en realidad una constante que nunca cambia, usa const:

\n\n
const MAX_CONNECTIONS: u32 = 100;\nconst DATABASE_URL: &str = "postgresql://localhost:5432/mydb";\n\nfn main() {\n    println!("Máximo de conexiones: {}", MAX_CONNECTIONS);\n}
\n\n

Las constantes en Rust no son solo variables. El compilador las inlinea en el lugar de uso. Es decir, durante la compilación, MAX_CONNECTIONS se reemplazará por el número 100. Esto es eficiente, pero significa que la constante no tiene una dirección fija en memoria. Si necesitas una ubicación en memoria (por ejemplo, para FFI), usa static.

\n\n

Método 2: Variables estáticas (static)

\n\n

Si necesitas una variable global con una dirección fija en memoria, usa static:

\n\n
static APP_NAME: &str = "My Rust Application";\nstatic VERSION: u32 = 1;\n\nfn main() {\n    println!("Iniciando {} versión {}", APP_NAME, VERSION);\n}
\n\n

Por defecto, las variables static son inmutables. Esto garantiza la seguridad en entornos multihilo. Pero, ¿qué pasa si necesitas modificar el estado global?

\n\n

Método 3: Variables estáticas mutables (static mut) — cuidado, unsafe!

\n\n

Rust permite declarar una variable estática mutable con static mut. Pero hay un truco: cualquier lectura o escritura de dicha variable requiere un bloque unsafe.

\n\n
static mut COUNTER: u32 = 0;\n\nfn increment() {\n    unsafe {\n        COUNTER += 1;\n    }\n}\n\nfn main() {\n    increment();\n    unsafe {\n        println!("Contador: {}", COUNTER);\n    }\n}
\n\n

Importante:

Blogs

Book Recommendations