Dans le cas où votre programme golang est lancé en tant que service, il peut être utile d’obtenir l’emplacement de l’exécutable et non le répertoire de travail. Un cas d’usage serait d’accéder à un fichier de configuration qui est dans le même répertoire que l’exécutable ou à un sous-répertoire qui contiendrait des données ou vos templates.
Prenons l’exemple d’une ressource config.json contenue dans le répertoire d’installation de votre programme go. Avec Windows, si vous tentez d’accéder à cette ressource avec le chemin relatif ./config.json, le programme tentera d’accéder à %WinDir%\System32\config.json qui est le répertoire de travail des services Windows.
On pourrait être tenté d’utiliser os.Getwd(), mais cette fonction ne retournera le bon répertoire que si le programme a été lancé de manière interactive (depuis la console, par exemple) et pas dans le cas d’un service. En outre, si votre programme ou une bibliothèque tierce modifie le répertoire de travail (avec os.Chdir()) le résultat de la fonction ne sera plus valide.
Comme expliqué dans un autre de mes articles, os.Args[0] ne fonctionnera pas forcément à tous les coups.
Il existe une bibliothèque tierce (kardianos/osext) qui est capable de retrouver chemin de l’exécutable golang quel que soit le système d’exploitation (le principe de fonctionnement est décrit plus loin). On installe donc le paquet qui va bien en exécutant ces commandes à la console :
go get bitbucket.org/kardianos/osext go install bitbucket.org/kardianos/osext
Puis, on inclut ce code en début de fichier :
import "bitbucket.org/kardianos/osext"
La ligne de code permettant de récupérer le chemin de l’exécutable golang est la suivante :
exePath, _ := osext.ExecutableFolder()
Sous Linux, on peut obtenir le chemin de l’exécutable golang en lisant dans le répertoire /proc. Par exemple, si votre exécutable a pour PID 41, on obtient son chemin en lisant le lien /proc/41/exe.
pid := os.Getpid() lnk := "/proc/" + strconv.Itoa(pid) + "/exe" p, err = os.Readlink(lnk)
Sous Windows, il faut faire appel à la fonction GetModuleFileNameW de la bibliothèque kernel32.dll
func getModuleFileName(buflen uint32, buf *uint16) (n uint32, err error) { h, err := syscall.LoadLibrary("kernel32.dll") if err != nil { return 0, err } defer syscall.FreeLibrary(h) addr, err := syscall.GetProcAddress(h, "GetModuleFileNameW") if err != nil { return 0, err } r0, _, e1 := syscall.Syscall(addr, 3, uintptr(0), uintptr(unsafe.Pointer(buf)), uintptr(buflen)) n = uint32(r0) if n == 0 { if e1 != 0 { err = error(e1) } else { err = syscall.EINVAL } } return }
Traduction d'une partie des spécifications officielles du langage Go, cet article explique comment développer en Go. Lire »
Une traduction du blog officiel de golang expliquant le mécanisme de la réflexion en Go. Lire »
Créer et déployer un service golang sous Linux, Windows et MacOS. La bibliothèque kardianos/service permet de créer, lancer et arrêter un service Go Lire »
Exemples concrets d'utilisation des fonctions de gestion des erreurs, d'arrêt anormal de l'exécution d'un programe et de récupération. Lire »
Traduction d'un article du blog officiel expliquant comment échanger des données entre deux programmes golang grâce à un format natif Lire »
Soyez le premier à commenter cet article
Tous les commentaires sont soumis à modération. Les balises HTML sont pour la plupart autorisées. Les liens contextuels et intéressants sont en follow.