Verzeichnislisting in Go: Vom Einfachen zum Komplexen
\n\nDie Arbeit mit dem Dateisystem ist eine der grundlegenden Aufgaben jeder Programmiersprache. In Go ist sie so elegant umgesetzt, dass selbst eine so routinemäßige Operation wie list directory in Go zu einem spannenden Abenteuer wird. Wenn Sie sich jemals gefragt haben: "Wie bekomme ich eine Liste der Dateien in einem Ordner in Go?" – sind Sie hier genau richtig. Heute werden wir alle möglichen Methoden durchgehen, von der einfachen Ausgabe bis zum rekursiven Durchlauf mit Filterung.
\n\nWarum ist dieses Thema auf Stack Overflow so beliebt? Weil Go gleich mehrere Ansätze bietet, und den richtigen zu wählen, ist die halbe Miete. Wir betrachten das klassische os.ReadDir, das veraltete ioutil.ReadDir (das man aber immer noch in alten Projekten findet) und das leistungsstarke filepath.Walk für den rekursiven Durchlauf. Los geht's!
1. Einfachstes Listing: os.ReadDir
\n\nSeit Go 1.16 hat das Paket os die neue Methode ReadDir erhalten, die zum De-facto-Standard geworden ist. Sie gibt einen Slice von os.DirEntry-Objekten zurück – leichte Beschreibungen von Dateien und Ordnern. So sieht das aus:
package main\n\nimport (\n "fmt"\n "os"\n "log"\n)\n\nfunc main() {\n // Liest den Inhalt des aktuellen Verzeichnisses\n entries, err := os.ReadDir(".")\n if err != nil {\n log.Fatal(err)\n }\n\n fmt.Println("Inhalt des aktuellen Ordners:")\n for _, entry := range entries {\n fmt.Printf("- %s (Verzeichnis: %v)\\n", entry.Name(), entry.IsDir())\n }\n}\n\n\nDieser Code gibt alle Dateien und Ordner im aktuellen Verzeichnis aus. Beachten Sie: os.ReadDir liest keine Unterordner – nur die erste Ebene. Wenn Sie ein list directory in Go rekursiv benötigen, lesen Sie weiter.
2. ioutil.ReadDir: Alt, aber vertraut
\n\nVor Go 1.16 verwendeten alle ioutil.ReadDir. Es gibt []os.FileInfo zurück – eine schwerere Struktur mit vollständigen Dateiinformationen (Größe, Zugriffsrechte, Änderungsdatum). Obwohl die Methode als deprecated markiert ist, können Sie ihr immer noch in Legacy-Code begegnen:
package main\n\nimport (\n "fmt"\n "io/ioutil"\n "log"\n)\n\nfunc main() {\n files, err := ioutil.ReadDir("./mydir")\n if err != nil {\n log.Fatal(err)\n }\n\n fmt.Println("Dateien in mydir (alte Methode):")\n for _, file := range files {\n fmt.Printf("Name: %s, Größe: %d Bytes\\n", file.Name(), file.Size())\n }\n}\n\n\nDer Hauptunterschied: ioutil.ReadDir sortiert das Ergebnis nach Dateinamen (wie ls), os.ReadDir hingegen nicht. Wenn die Reihenfolge wichtig ist, verwenden Sie sort.Slice oder eine manuelle Sortierung.
3. Rekursiver Durchlauf mit filepath.Walk
\n\nWenn Sie alle Unterordner durchgehen müssen, kommt filepath.Walk zur Hilfe. Diese Funktion durchläuft den Verzeichnisbaum und ruft für jedes gefundene Element einen Callback auf. Ideal für Backups, Dateisuche oder die Analyse der Projektstruktur:
package main\n\nimport (\n "fmt"\n "os"\n "path/filepath"\n)\n\nfunc main() {\n root := "./myproject"\n err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {\n if err != nil {\n return err\n }\n fmt.Printf("Gefunden: %s (Größe: %d)\\n", path, info.Size())\n return nil\n })\n if err != nil {\n fmt.Println("Fehler beim Durchlauf:", err)\n }\n}\n\n\nEin wichtiger Punkt: filepath.Walk folgt Symlinks und kann in eine Endlosschleife geraten, wenn zyklische Verweise vorhanden sind. Verwenden Sie für die Produktion filepath.WalkDir (Go 1.16+) – es ist leichter und sicherer.
4. Filterung: Nur .go-Dateien oder nur Ordner
\n\nOft benötigt man nicht alles, sondern nur bestimmte Dateitypen. Lassen Sie uns eine Filterung mit strings.HasSuffix und der Prüfung IsDir() implementieren.