Wo ist meine Datei? Lerne Go, um deinen Weg zu finden

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: "Wo bin ich?" – fragt das Programm

\n

Stellen Sie sich vor: Sie schreiben ein Dienstprogramm in Go, das eine Konfiguration aus einem Ordner neben seiner ausführbaren Datei lesen soll. Oder Sie erstellen eine Log-Datei im selben Verzeichnis, in dem sich das Programm befindet. Es scheint einfach, oder? Aber dann wird es interessant: Go ist eine kompilierte Sprache und hat ihre eigenen "Geheimnisse", wenn es darum geht, den eigenen Standort zu ermitteln.

\n

Die Frage "How to get the directory of the currently running file?" ist eine der beliebtesten auf Stack Overflow unter Go-Neulingen. Und das nicht ohne Grund. Im Gegensatz zu Skriptsprachen, wo __file__ (Python) oder __dirname (Node.js) alles im Handumdrehen lösen, muss man in Go überlegen: Welche Datei interessiert uns eigentlich? Der Quellcode (während der Kompilierung) oder die ausführbare Binärdatei (während der Ausführung)?

\n

In diesem Artikel werden wir beide Ansätze behandeln, lernen, typische Fallstricke zu vermeiden, und einige Go-Codebeispiele schreiben, die Sie in realen Projekten verwenden können. Los geht's!

\n\n

Zwei Welten, zwei Kindheiten: Quelle vs. Binärdatei

\n

Bevor wir Code schreiben, lassen Sie uns das Hauptdilemma verstehen. In Go wird ein Programm zuerst in eine statische Binärdatei kompiliert. Wenn Sie go run main.go ausführen, erstellt Go eine temporäre ausführbare Datei und führt sie aus. Wenn Sie go build ausführen, erhalten Sie eine fertige Datei, die Sie auf einen anderen Computer übertragen können.

\n

Daher hat die Frage "Wo bin ich?" zwei Antworten:

\n
    \n
  • Pfad zur Quelldatei – wird während der Entwicklung für Logging oder Tests benötigt.
  • \n
  • Pfad zur ausführbaren Datei – wird in der Produktion benötigt, um nahegelegene Ressourcen (Konfigurationen, Datenbanken usw.) zu finden.
  • \n
\n

Die meisten Antworten auf Stack Overflow beziehen sich auf die zweite Option, aber wir werden beide behandeln, damit Sie bestens gerüstet sind.

\n\n

Methode Nr. 1: Das Verzeichnis der ausgeführten Binärdatei ermitteln

\n

Dies ist das häufigste Szenario. Ihr Programm wurde bereits kompiliert und ausgeführt, und es muss herausfinden, aus welchem Ordner es gestartet wurde. Go bietet dafür eine elegante Möglichkeit – das Paket os und die Funktion os.Executable().

\n\n

Codebeispiel: Basisvariante

\n
package main\n\nimport (\n    "fmt"\n    "os"\n    "path/filepath"\n)\n\nfunc main() {\n    // Den vollständigen Pfad zur ausführbaren Datei abrufen\n    exePath, err := os.Executable()\n    if err != nil {\n        fmt.Println("Fehler beim Abrufen des Pfads:", err)\n        return\n    }\n    fmt.Println("Vollständiger Pfad zur Binärdatei:", exePath)\n\n    // Das Verzeichnis extrahieren\n    exeDir := filepath.Dir(exePath)\n    fmt.Println("Verzeichnis der ausführbaren Datei:", exeDir)\n}
\n

Führen Sie diesen Code mit go run main.go aus – Sie sehen einen Pfad wie /tmp/go-build123456/b001/exe/main. Dies ist ein temporäres Verzeichnis. Wenn Sie kompilieren (go build -o myapp) und ./myapp ausführen, erhalten Sie das aktuelle Verzeichnis.

\n\n

Fallstricke: Symlinks und chdir

\n

Die Funktion os.Executable() gibt den Pfad zurück, unter dem das Programm gestartet wurde. Es gibt jedoch Nuancen:

\n
    \n
  • Symbolische Links. Wenn Sie das Programm über einen Symlink gestartet haben (/usr/local/bin/myapp -> /opt/myapp_v2/myapp), gibt os.Executable() den Pfad zum Link selbst zurück, nicht zur eigentlichen Datei. Um den "echten" Pfad zu erhalten, verwenden Sie filepath.EvalSymlinks().
  • \n
  • Änderung des Arbeitsverzeichnisses. Wenn das Programm intern os.Chdir() aufruft, hat dies keinen Einfluss auf os.Executable() – es gibt weiterhin den Pfad zur Binärdatei zurück.
  • \n
\n\n

Verbesserte Version mit Symlink-Behandlung

\n
package main\n\nimport (\n    "fmt"\n    "os"\n    "path/filepath"\n)\n\nfunc main() {\n    exePath, err := os.Executable()\n    if err != nil {\n        panic(err)\n    }\n\n    //                

Blogs

Buchempfehlungen