Introduction : « Où suis-je ? » demande le programme
\nImaginez : vous écrivez en Go un utilitaire qui doit lire un fichier de configuration dans un dossier situé à côté de son fichier exécutable. Ou, par exemple, vous créez un fichier journal dans le même répertoire que celui où se trouve le programme. Cela semble simple, non ? Mais c'est là que les choses deviennent intéressantes : Go est un langage compilé, et il a ses « secrets » lorsqu'il s'agit de connaître son propre emplacement.
\nLa question "How to get the directory of the currently running file?" est l'une des plus populaires sur Stack Overflow parmi les débutants en Go. Et ce n'est pas un hasard. Contrairement aux langages de script, où __file__ (Python) ou __dirname (Node.js) résolvent tout en un clin d'œil, en Go, il faut réfléchir : quel fichier nous intéresse exactement ? Le code source (lors de la compilation) ou le binaire exécutable (lors de l'exécution) ?
Dans cet article, nous aborderons les deux approches, apprendrons à éviter les pièges courants et écrirons plusieurs exemples de code en Go que vous pourrez utiliser dans des projets réels. C'est parti !
\n\nDeux mondes, deux réalités : source vs binaire
\nAvant d'écrire du code, comprenons le dilemme principal. En Go, le programme est d'abord compilé en un binaire statique. Lorsque vous exécutez go run main.go, Go crée un fichier exécutable temporaire et l'exécute. Lorsque vous faites go build, vous obtenez un fichier prêt à être transféré sur un autre ordinateur.
Par conséquent, la question « où suis-je ? » a deux réponses :
\n- \n
- Le chemin vers le fichier source — nécessaire pendant le développement, pour la journalisation ou les tests. \n
- Le chemin vers le fichier exécutable — nécessaire en production pour trouver les ressources situées à proximité (fichiers de configuration, bases de données, etc.). \n
La plupart des réponses sur Stack Overflow concernent la deuxième option, mais nous examinerons les deux pour que vous soyez parfaitement armé.
\n\nMéthode n°1 : Connaître le répertoire du binaire en cours d'exécution
\nC'est le scénario le plus courant. Votre programme est déjà compilé et exécuté, et il doit comprendre depuis quel dossier il a été lancé. Go offre un moyen élégant pour cela : le package os et la fonction os.Executable().
Exemple de code : version de base
\npackage main\n\nimport (\n "fmt"\n "os"\n "path/filepath"\n)\n\nfunc main() {\n // Obtenir le chemin complet vers le fichier exécutable\n exePath, err := os.Executable()\n if err != nil {\n fmt.Println("Erreur lors de l'obtention du chemin :", err)\n return\n }\n fmt.Println("Chemin complet vers le binaire :", exePath)\n\n // Extraire le répertoire\n exeDir := filepath.Dir(exePath)\n fmt.Println("Répertoire du fichier exécutable :", exeDir)\n}\nExécutez ce code avec go run main.go — vous verrez un chemin comme /tmp/go-build123456/b001/exe/main. C'est un répertoire temporaire. Mais si vous compilez (go build -o myapp) et exécutez ./myapp — vous obtiendrez le dossier courant.
Pièges à éviter : liens symboliques et chdir
\nLa fonction os.Executable() renvoie le chemin par lequel le programme a été lancé. Mais il y a des nuances :
- \n
- Liens symboliques. Si vous avez lancé le programme via un lien symbolique (
/usr/local/bin/myapp -> /opt/myapp_v2/myapp),os.Executable()renverra le chemin vers le lien lui-même, et non vers le fichier réel. Pour obtenir le chemin « réel », utilisezfilepath.EvalSymlinks(). \n - Changement du répertoire de travail. Si le programme appelle
os.Chdir()en interne, cela n'affecte en rienos.Executable()— elle renverra toujours le chemin vers le binaire. \n
Version améliorée avec gestion des liens symboliques
\npackage 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 //