Introduction: "Where are the global variables?" — A beginner's first shock in Rust
\n\nYou've just started learning Rust, written a couple of programs, and suddenly realize: you need a variable to be accessible from anywhere in the code. In Python or JavaScript, you'd simply write global_var = 42 at the top level — and you're done. But in Rust... the compiler looks at you reproachfully and throws an error.
The question "Is it possible to use global variables in Rust?" is one of the most popular on Stack Overflow. And for good reason. Rust, unlike many languages, does not allow you to simply declare a global variable. Why? Because memory safety is not just a buzzword, but the foundation of the language.
\n\nIn this article, we'll break down all the ways to work with global data in Rust: from simple constants to thread-safe storage. You'll learn how to bypass compiler limitations without sacrificing safety, and when global variables are evil, and when they are a necessity.
\n\nWhy does Rust forbid "ordinary" global variables?
\n\nBefore looking for solutions, let's understand the problem. Rust has strict rules of ownership and borrowing. A global variable that can be modified from any thread at any moment is a direct path to a data race.
\n\nImagine: two threads simultaneously try to write different values to the same global variable. The result is unpredictable. In C++ or C, this leads to undefined behavior. Rust guarantees that such code simply won't compile.
\n\nTherefore, the compiler requires us to explicitly specify:
\n- \n
- Is the variable immutable? Use
constorstatic. \n - Is the variable mutable and used in a single thread? Use
static mut(withunsafe). \n - Is the variable mutable and used in multiple threads? Use
Mutex,RwLock, or atomic types. \n
Method 1: Constants (const) — the safest option
\n\nIf your "global value" is actually a constant that never changes, use const:
const MAX_CONNECTIONS: u32 = 100;\nconst DATABASE_URL: &str = "postgresql://localhost:5432/mydb";\n\nfn main() {\n println!("Maximum connections: {}", MAX_CONNECTIONS);\n}\n\nConstants in Rust are not just variables. They are inlined by the compiler at the point of use. That is, during compilation, MAX_CONNECTIONS will be replaced with the number 100. This is efficient, but it means the constant has no fixed address in memory. If you need a specific memory location (e.g., for FFI), use static.
Method 2: Static variables (static)
\n\nIf you need a global variable with a fixed memory address, use static:
static APP_NAME: &str = "My Rust Application";\nstatic VERSION: u32 = 1;\n\nfn main() {\n println!("Starting {} version {}", APP_NAME, VERSION);\n}\n\nBy default, static variables are immutable. This guarantees safety in a multithreaded environment. But what if you need to modify global state?
Method 3: Mutable static variables (static mut) — caution, unsafe!
\n\nRust allows you to declare a mutable static variable using static mut. But there's a catch: any reading or writing of such a variable requires an unsafe block.
static mut COUNTER: u32 = 0;\n\nfn increment() {\n unsafe {\n COUNTER += 1;\n }\n}\n\nfn main() {\n increment();\n unsafe {\n println!("Counter: {}", COUNTER);\n }\n}\n\nImportant: