Warum die Arbeit mit Dateien in Go nicht beängstigend, sondern interessant ist?
\n\nAls ich zum ersten Mal die Dokumentation des Pakets os in Go öffnete, dachte ich, mich erwarte eine langweilige Aufzählung von Systemaufrufen. Aber als ich tiefer grub, verstand ich: Die Arbeit mit Dateien und dem Dateisystem in Go ist nicht nur das Lesen von Bytes. Es ist ein mächtiges Werkzeug, das Ihnen die volle Kontrolle über Daten gibt, seien es Konfigurationsdateien, Logs, Binärdateien oder ganze Datenbanken in CSV.
Go wurde für die Systemprogrammierung entwickelt, daher haben seine Autoren (Ken Thompson, Rob Pike und andere) die Arbeit mit Dateien direkt in den Kern der Sprache eingebaut. Keine externen Abhängigkeiten, nur die Standardbibliothek, die schnell und vorhersagbar arbeitet. In diesem Artikel werden wir alle Szenarien durchgehen: vom einfachen Lesen einer Datei bis zum rekursiven Durchlaufen von Verzeichnissen und der Streaming-Verarbeitung großer Datenmengen.
\n\nWenn Sie in Go programmieren und sicher mit dem Dateisystem arbeiten möchten, sind Sie hier richtig. Los geht's!
\n\nGrundlagen: Öffnen, Lesen, Schließen
\n\nDer allererste Schritt ist das Öffnen einer Datei. In Go ist dafür die Funktion os.Open() zuständig. Sie gibt einen Zeiger auf die Datei und einen Fehler zurück. Fehler in Go sind keine Ausnahmen, sondern Werte. Sie müssen immer überprüft werden.
package main\n\nimport (\n "fmt"\n "os"\n)\n\nfunc main() {\n file, err := os.Open("example.txt")\n if err != nil {\n fmt.Println("Fehler beim Öffnen der Datei:", err)\n return\n }\n defer file.Close() // Datei unbedingt schließen\n\n // Inhalt lesen\n buf := make([]byte, 1024)\n n, err := file.Read(buf)\n if err != nil {\n fmt.Println("Fehler beim Lesen:", err)\n return\n }\n fmt.Printf("Gelesen %d Bytes: %s\\n", n, string(buf[:n]))\n}\n\n\nBeachten Sie defer file.Close(). Dies ist eine Go-Idiom: Der verzögerte Aufruf stellt sicher, dass die Datei auch im Falle einer Panik oder einer vorzeitigen Rückkehr geschlossen wird. Das Vergessen, eine Datei zu schließen, ist eine schlechte Praxis, die zu Deskriptorlecks führt.
Eine ganze Datei in einer Zeile lesen
\n\nWenn die Datei klein ist (bis zu einigen Megabyte), können Sie os.ReadFile() verwenden (ersetzt das veraltete ioutil.ReadFile). Dies ist praktisch für Konfigurationen oder Textdaten.
data, err := os.ReadFile("config.yaml")\nif err != nil {\n log.Fatal(err)\n}\nfmt.Println(string(data))\n\n\nDie Funktion öffnet, liest und schließt die Datei selbst. Aber denken Sie daran: Für große Dateien ist dieser Ansatz gefährlich – Sie laden die gesamte Datei in den Speicher.
\n\nIn eine Datei schreiben: Erstellen und Anhängen
\n\nVerwenden Sie zum Schreiben os.Create() (erstellt eine neue Datei oder schneidet eine vorhandene ab) und os.OpenFile() für eine feinere Konfiguration (z. B. Anhängen an das Ende).
// Datei erstellen\nfile, err := os.Create("output.txt")\nif err != nil {\n panic(err)\n}\ndefer file.Close()\n\n// Zeichenkette schreiben\n_, err = file.WriteString("Hallo, Go Dateien!\\n")\nif err != nil {\n panic(err)\n}\n\n// Bytes schreiben\nbytes := []byte("Schreiben eines Byte-Slices\\n")\n_, err = file.Write(bytes)\nif err != nil {\n panic(err)\n}\n\n\nVerwenden Sie zum Anhängen von Daten an das Ende einer vorhandenen Datei die Flags:
\n\nfile, err := os.OpenFile("log.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)\nif err != nil {\n log.Fatal(err)\n}\ndefer file.Close()\n\nfile.WriteString("Neuer Logeintrag\\n")\n\n\nDas Flag os.O_APPEND stellt sicher, dass die Daten an das Ende angehängt werden und nicht den Anfang überschreiben.
Arbeiten mit Verzeichnissen: Erstellen, Löschen, Durchlaufen
\n\nDas Dateisystem besteht nicht nur aus Dateien, sondern auch aus Ordnern. Go bietet praktische Funktionen für die Arbeit mit Verzeichnissen.
\n\nOrdner erstellen und löschen
\n\n// Einen Ordner erstellen\nerr := os.Mkdir("newdir", 0755)\nif err != nil {\n log.Fatal(err)\n}\n\n// Verschachtelte Ordner erstellen (wie mkdir -p)\nerr = os.MkdirAll("path/to/nested/dir", 0755)\nif err != nil {\n log.Fatal(err)\