Einleitung: "Wo sind hier die globalen Variablen?" – der erste Schock für Rust-Neulinge
\n\nSie haben gerade angefangen, Rust zu lernen, ein paar Programme geschrieben, und plötzlich merken Sie: Sie brauchen eine Variable, die von jeder Stelle im Code aus zugänglich ist. In Python oder JavaScript würden Sie einfach global_var = 42 auf der obersten Ebene schreiben – und fertig. Aber in Rust... der Compiler sieht Sie vorwurfsvoll an und gibt einen Fehler aus.
Die Frage "Is it possible to use global variables in Rust?" ist eine der beliebtesten auf Stack Overflow. Und das zu Recht. Rust erlaubt es im Gegensatz zu vielen Sprachen nicht, einfach so eine globale Variable zu deklarieren. Warum? Weil Speichersicherheit nicht nur ein Modewort ist, sondern das Fundament der Sprache.
\n\nIn diesem Artikel analysieren wir alle Möglichkeiten, mit globalen Daten in Rust zu arbeiten: von einfachen Konstanten bis hin zu threadsicheren Speichern. Sie erfahren, wie Sie die Einschränkungen des Compilers umgehen können, ohne die Sicherheit zu opfern, und wann globale Variablen böse sind und wann eine Notwendigkeit.
\n\nWarum verbietet Rust "normale" globale Variablen?
\n\nBevor wir nach Lösungen suchen, lassen Sie uns das Problem verstehen. In Rust gelten strenge Regeln für Ownership und Borrowing. Eine globale Variable, die von jedem Thread aus jederzeit geändert werden kann, ist der direkte Weg zu einer Data Race.
\n\nStellen Sie sich vor: Zwei Threads versuchen gleichzeitig, unterschiedliche Werte in dieselbe globale Variable zu schreiben. Das Ergebnis ist unvorhersehbar. In C++ oder C führt dies zu undefiniertem Verhalten. Rust hingegen garantiert, dass so etwas einfach nicht kompiliert wird.
\n\nDaher verlangt der Compiler von uns, explizit anzugeben:
\n- \n
- Ist die Variable unveränderlich? Verwenden Sie
constoderstatic. \n - Ist die Variable veränderlich und wird in einem einzelnen Thread verwendet? Verwenden Sie
static mut(mitunsafe). \n - Ist die Variable veränderlich und wird in mehreren Threads verwendet? Verwenden Sie
Mutex,RwLockoder atomare Typen. \n
Methode 1: Konstanten (const) – die sicherste Option
\n\nWenn Ihr "globaler Wert" tatsächlich eine Konstante ist, die sich nie ändert, verwenden Sie const:
const MAX_CONNECTIONS: u32 = 100;\nconst DATABASE_URL: &str = "postgresql://localhost:5432/mydb";\n\nfn main() {\n println!("Maximale Verbindungen: {}", MAX_CONNECTIONS);\n}\n\nKonstanten in Rust sind nicht einfach Variablen. Sie werden vom Compiler inline an der Verwendungsstelle eingesetzt. Das heißt, während der Kompilierung wird MAX_CONNECTIONS durch die Zahl 100 ersetzt. Das ist effizient, bedeutet aber, dass die Konstante keine feste Speicheradresse hat. Wenn Sie eine Speicheradresse benötigen (z. B. für FFI), verwenden Sie static.
Methode 2: Statische Variablen (static)
\n\nWenn Sie eine globale Variable mit einer festen Speicheradresse benötigen, verwenden Sie static:
static APP_NAME: &str = "My Rust Application";\nstatic VERSION: u32 = 1;\n\nfn main() {\n println!("Starte {} Version {}", APP_NAME, VERSION);\n}\n\nStandardmäßig sind static-Variablen unveränderlich. Dies garantiert Sicherheit in einer Multithread-Umgebung. Aber was ist, wenn Sie den globalen Zustand ändern müssen?
Methode 3: Veränderliche statische Variablen (static mut) – Vorsicht, unsafe!
\n\nRust erlaubt es, eine veränderliche statische Variable mit static mut zu deklarieren. Aber es gibt einen Haken: Jedes Lesen oder Schreiben einer solchen Variable erfordert einen 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!("Zähler: {}", COUNTER);\n }\n}\n\nWichtig: