Dateien öffnen und schließen in Rust
Rusts Kernfeature ist das sogenannte Ownership. Es beschreibt die Idee, dass jeder Datentyp gleichzeitig eine Resource darstellt. Rust löst das darüber, dass es jedem Stück Daten einen sogenannten Owner zuweist. Erstelle ich mit File::create eine Datei, bekomme ich im Erfolgsfall nicht nur ein File-Objekt zurück, sondern auch die Verantwortung des Managements. Ich besitze die Datei und bin der einzige Besitzer. Gebe ich den Besitz auf irgendeine Art auf, wird die Datei geschlossen.
Daten in Rust haben also einen modellierten Lebenszyklus. Im Gegensatz zu vielen anderen Sprachen ist dieses Konzept keine Konvention, sondern einer der Grundpfeiler des Typsystems. Deswegen begegnet es einem auch sofort und muss gelernt werden - es führt kein Weg daran vorbei.
Als einfaches Beispiel ein kleines Programm, das eine Datei erstellt, etwas hineinschreibt und die Datei schließt:
fn main() -> Result<(), io::Error> { let open_file: Result<File, io::Error> = File::create("hello_golem.txt"); match open_file { Ok(mut file) => { file.write_all(b"Hallo Golem!") // *** hier wird die Datei aufgegeben und damit geschlossen } Err(e) => { eprintln!("Datei konnte nicht erstellt werden. Fehler: {}", e); Err(e) } } }
Sie finden den Code zum live Ausprobieren auch auf dem offiziellen Rust Playground. Lassen Sie sich von der verbosen Fehlerbehandlung nicht zu sehr beeindrucken - ich habe sie aus Illustrationsgründen ausgeschrieben.
Potenzielle Fehler werden in Rust über enum-Datentypen dargestellt. Diese bilden mehrere Alternativen ab, im Fall von Resultaten zwei. Diese Funktion gibt entweder eine Zahl zurück (die Anzahl der geschriebenen Bytes) oder einen potenziellen I/O-Fehler.
Das zwingt die aufrufende Funktion, auf beide Varianten zu prüfen und eventuell Fehlerbehandlung zu betreiben. Im Gegensatz zu den oben beschriebenen Konzepten ist Result hier ein Typ, der streng genommen kein Sprachbestandteil ist, aber durch die Standardbibliothek mitgeliefert wird.
Das Sprachkonstrukt ist der sogenannte match-Block, der die Fallunterscheidung zwischen den beiden Alternativen Ok (erfolgreich) und Err (Fehler sind aufgetreten) darstellt. Um hier schon mal die Idee des Ownership zu betrachten: Der Aufruf der create-Funktion bringt uns erst mal in den Besitz eines Resultats. Dieses Resultat besitzt die offene Datei - im Erfolgsfall. Möchten wir Zugriff auf die Datei, muss erst geprüft werden, ob dieser auch vorliegt. Rust zwingt uns hier also zur Fehlerprüfung aus dem Ownership-Konzept heraus.
Das mag zu Beginn anstrengend sein, entfaltet seine Wirkung jedoch schnell auf größeren Codebasen. Denn sie führt ganz natürlich dazu, dass keine Fehlerfälle vergessen werden, sondern früh direkt in den Coding-Workflow eingebunden werden.
Rustc ist detailverliebt
Wie wendet Rust diese Ideen weiter an? Als Beispiel möchte ich eine Funktion nehmen, die eine Datei und eine Zeichenkette übernimmt und diese schreibt. Sehen wir uns folgenden Funktionsprototyp an:
fn write_to_file(file: File, string_buffer: String) -> Result<usize, io::Error> { // Implementierung ausgelassen }
Werden Typen einfach nur mit ihrem Namen übergeben, übergibt Rust eben diesen Besitz.
Oder nutzen Sie das Golem-pur-Angebot
und lesen Golem.de
- ohne Werbung
- mit ausgeschaltetem Javascript
- mit RSS-Volltext-Feed
Programmiersprachen: Weniger Frust mit Rust | Rust macht es unmöglich, in eine geschlossene Datei zu schreiben |
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