Rust macht es unmöglich, in eine geschlossene Datei zu schreiben
In Rust enthalten Funktionssignaturen also noch viel mehr: Hier übergibt die aufrufende Funktion den Besitz und die aufgerufene. Kurz heißt das hier, dass die Funktion nicht nur eine Datei als Argument kriegt, sondern dabei auch das Management übernimmt.
Da der Lebenszyklus eines File-Pointers über das Besitzkonzept modelliert ist, haben wir die Garantie, dass das File immer offen ist. Es wird erst geschlossen, wenn der Besitzer den Besitz aufgibt. Und das ist auch die einzige Art, die Datei zu schließen, denn eine klassische close-Funktion gibt es nicht.
Da aber kein Garbage-Kollektor zum Einsatz kommt, ist der Vorgang dennoch sicher. Wir können nicht aus Versehen in geschlossene Dateien schreiben. Der zu schreibende String ist auf jeden Fall vorhanden, wir müssen aber nicht prüfen.
Schauen wir uns hier einmal einen Fehler an:
let file = File::create("test"); // Fehlerbehandlung write_to_file(file, String::from("Hallo Golem!")); // Besitzabgabe write_to_file(file, String::from("Hallo Golem!")); // !!!!
Nach meiner Erklärung zuvor sollte das Problem hier klar sein: Ich muss davon ausgehen, dass die Datei nach dem Aufruf dieser Funktion geschlossen ist - nach Rusts Verständnis also auch kein gültiger File-Pointer mehr existiert. Der Compiler erkennt diese Probleme.
Die Fehlermeldung in Gänze können Sie in diesem Playground-Link betrachten. Die Lösung für diese Fehler ist allerdings nicht direkt ersichtlich: Denn dieses Verhalten kann, wie später ausgeführt, strukturell gewünscht sein und ein Sicherheitsnetz darstellen.
Aus den Rückgabetypen können wir lesen, dass wir den Besitz nicht zurückbekommen. Wir müssen daher davon ausgehen, dass die Datei dann geschlossen ist. Wir übernehmen auch den Besitz von string_buffer, der danach aus dem Speicher entfernt wird. Möchten wir das nicht, hilft ein weiteres Sprachkonstrukt, das der Referenzen:
fn write_to_file(file: File, string_buffer: &str) -> Result<usize, io::Error> { // Implementierung ausgelassen }
Hier wird eine Funktion beschrieben, die zwar das Dateimanagement übernimmt, aber nicht das Management des String-Speichers. Die Referenz ist hier eine sogenannte immutable Referenz: Sie kann mehrfach existieren und geteilt werden, aber der Besitzer des referenzierten Strings ist dafür verantwortlich (in diesem Fall die aufrufende Funktion), sie valide - und damit den String im Speicher - zu halten. Funktionen, die eine immutable Referenz erhalten, können sich sicher sein, dass der Wert hinter der Referenz sich niemals ändert. Der Compiler setzt diese Regel durch.
Ich möchte an dieser Stelle nicht zu stark auf Fehlermeldungen eingehen. Der wichtige Punkt ist hier, dass wir statt des Erstellens zweier Strings einen verwenden können.
let buffer = "Hallo Golem!"; write_to_file(file1, &buffer); write_to_file(file2, &buffer);
Aber wie sieht es mit der Datei aus?
fn write_to_file(file: &mut File, string_buffer: &str) -> Result<usize, io::Error> { // Implementierung ausgelassen }
Im Gegensatz zum letzten Prototyp referenziert diese Funktion auch unser File. Allerdings anders, denn wir möchten in diese Datei schreiben. &mut ist hierbei eine sogenannte mutable Referenz.
Oder nutzen Sie das Golem-pur-Angebot
und lesen Golem.de
- ohne Werbung
- mit ausgeschaltetem Javascript
- mit RSS-Volltext-Feed
Dateien öffnen und schließen in Rust | Mutable Referenzen lösen alle Nebenläufigkeitsprobleme |
oh wow, das ist krass, sehe gerade das nutzt https://crates.io/crates/druid
Jo ich meinte Rxjava und konsorten wobei ich für Vert.x schwärme :-) und eine Combo aus...
Was meinst du mit "DB Anwendung"? Gerade wenn man eine ordentliche Datenbank im...
So gemein das jetzt klingt - für die, die die Vorteile von solchen Sprachen nicht sehen...
Oh keine GUIs, alles singlethreaded, kein asynchroner I/O, keine Buffer? Über welche...
Kommentieren