Obtenir le répertoire personnel de l'utilisateur

90

La méthode suivante est-elle la meilleure façon d'obtenir le répertoire personnel de l'utilisateur en cours d'exécution? Ou y a-t-il une fonction spécifique que j'ai exagérée?

os.Getenv("HOME")

Si ce qui précède est correct, est-ce que quelqu'un sait si cette approche est garantie de fonctionner sur des plates-formes non Linux, par exemple Windows?

Paul Ruane
la source
2
$HOMEn'est pas nécessairement le répertoire personnel de l'utilisateur. Par exemple, je peux écrire export HOME=/something/elseavant de lancer votre programme. Habituellement, cela signifie que je veux que le programme le traite /something/elsecomme mon répertoire personnel pour une raison quelconque, et généralement le programme devrait l'accepter. Mais si vous avez vraiment besoin du répertoire personnel réel de l'utilisateur , une variable d'environnement ne vous le donnera pas nécessairement.
Keith Thompson
1
@KeithThompson Merci mais pour mes besoins, c'est assez bien.
Paul Ruane

Réponses:

174

Dans go 1.0.3 (probablement plus tôt aussi), les travaux suivants:

package main
import (
    "os/user"
    "fmt"
    "log"
)
func main() {
    usr, err := user.Current()
    if err != nil {
        log.Fatal( err )
    }
    fmt.Println( usr.HomeDir )
}

S'il est important d'effectuer une compilation croisée, considérez la homedirbibliothèque

Vlad Didenko
la source
1
Génial, merci beaucoup. N'était pas au courant de ce changement. Ceci est exactement ce que je cherchais.
Paul Ruane
Est-ce juste moi ou suis-je le seul où faire cela sous Windows prend plusieurs secondes?
Htbaa
Cela semble définitivement instantané sur ma machine virtuelle Windows 7 64 bits.
Vlad Didenko
4
Sachez qu'à partir de la version 1.1, "usr, err: = user.Current ()" lancera une erreur "user: Current not implementation on darwin / amd64" sur osx.
Oleiade
11
ne fonctionne pas en cas de compilation croisée de code.google.com/p/go/issues/detail?id=6376
Vishnu
55

os.UserHomeDir ()

Dans go1.12 +, vous pouvez utiliser os.UserHomeDir ()

home, err := os.UserHomeDir()

Voir https://golang.org/pkg/os/#UserHomeDir

Cela devrait fonctionner même sans CGO activé (c'est-à-dire FROM scratch) et sans avoir à analyser /etc/passwdou autre absurdité.

coolaj86
la source
22

Par exemple,

package main

import (
    "fmt"
    "os"
    "runtime"
)

func UserHomeDir() string {
    if runtime.GOOS == "windows" {
        home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
        if home == "" {
            home = os.Getenv("USERPROFILE")
        }
        return home
    }
    return os.Getenv("HOME")
}

func main() {
    dir := UserHomeDir()
    fmt.Println(dir)
}
peterSO
la source
1
C'est la même approche que Jeremy W Sherman qui semble être le seul moyen à l'heure actuelle. Merci beaucoup.
Paul Ruane
2
C'est l'approche suivie dans viper util.go userHomeDir ()
RubenLaguna
Dans presque tous les cas où je vois cela utilisé, ce n'est PAS la bonne chose à faire. USERPROFILEest la racine de l'espace de stockage de l'utilisateur sur le système, mais ce n'est PAS l'endroit où les applications doivent écrire en dehors d'une invite de dialogue d'enregistrement. Si vous avez une configuration d'application, elle doit être écrite APPDATAet si vous avez un cache d'application (ou des fichiers volumineux qui ne doivent pas se synchroniser sur un réseau), elle doit être écrite LOCALAPPDATAsous Windows.
Micah Zoltu le
4

Voici une manière agréable et concise de le faire (si vous utilisez uniquement un système UNIX):

import (
  "os"
)

var home string = os.Getenv("HOME")

Cela interroge simplement la variable d'environnement $ HOME.

--- Éditer ---

Je vois maintenant que cette même méthode a été suggérée ci-dessus. Je vais laisser cet exemple ici comme une solution distillée.

Murphy Randle
la source
2
1. cela a déjà été suggéré, 2. ce n'est pas multiplateforme, 3. la réponse acceptée résout déjà mieux ce problème.
Paul Ruane
3

Réponse similaire à @peterSO mais respecte le XDG_CONFIG_HOMEchemin pour linux.

package main

import (
    "fmt"
    "os"
    "runtime"
)

func userHomeDir() string {
    if runtime.GOOS == "windows" {
        home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
        if home == "" {
            home = os.Getenv("USERPROFILE")
        }
        return home
    } else if runtime.GOOS == "linux" {
        home := os.Getenv("XDG_CONFIG_HOME")
        if home != "" {
            return home
        }
    }
    return os.Getenv("HOME")
}

func main() {
    fmt.Println(userHomeDir())
}
Miguel Mota
la source
J'adorerais voir cette réponse mise à jour pour respecter Windows aussi! APPDATApour la configuration et LOCALAPPDATApour les gros fichiers. Pour une «maison» à usage général, je recommande LOCALAPPDATAdonc par défaut aux développeurs d'applications de ne pas détruire les réseaux d'entreprise. 😊
Micah Zoltu le
2

Vous devez utiliser la variable d'environnement USERPROFILEou HOMEPATHsous Windows. Voir Variables d'environnement reconnues (un lien de documentation plus à propos serait le bienvenu).

Jeremy W. Sherman
la source
Merci. Voulez-vous dire, alors, que HOME n'est pas peuplé par Go pour chaque plate-forme (qu'il délègue directement dans les variables d'environnement O / S) et que je dois vérifier la variable respective de chaque plate-forme pour identifier le répertoire de base?
Paul Ruane
J'ai jeté un coup d'œil à la source et il semble que HOME ne soit pas automatiquement rempli. Il semble qu'il n'y ait (actuellement) aucune installation indépendante de la plate-forme pour obtenir le répertoire personnel.
Paul Ruane
@PaulRuane Puisque les plates-formes utilisent des variables différentes, ignorez simplement le système d'exploitation, vérifiez les deux variables et choisissez celle qui est remplie. Si les deux sont définis, j'utiliserais HOME, car cela signifie probablement que vous utilisez cygwin.
Jeremy W. Sherman
Vous ne devez PAS utiliser USERPROFILEou HOMEPATHsous Windows dans la grande majorité des cas. Dans presque tous les cas où les développeurs les utilisent, ce qu'ils devraient utiliser est APPDATAou LOCALAPPDATA(selon qu'il est raisonnable que le contenu se synchronise sur le réseau lors de la connexion / déconnexion).
Micah Zoltu le
2

go1.8rc2 a la fonction go / build / defaultGOPATH qui récupère le répertoire personnel. https://github.com/golang/go/blob/go1.8rc2/src/go/build/build.go#L260-L277

Le code suivant est extrait de la fonction defaultGOPATH.

package main

import (
    "fmt"
    "os"
    "runtime"
)

func UserHomeDir() string {
    env := "HOME"
    if runtime.GOOS == "windows" {
        env = "USERPROFILE"
    } else if runtime.GOOS == "plan9" {
        env = "home"
    }
    return os.Getenv(env)
}

func main() {
    dir := UserHomeDir()
    fmt.Println(dir)
}
Hnakamur
la source
Bien que l'implémentation de cette fonction Go soit intéressante, c'est une solution pire que d'utiliser la fonction de bibliothèque standard décrite dans la réponse acceptée. (Et c'est la même approche que la réponse de peterSO d'il y a six ans.)
Paul Ruane
Ce n'est pas la bonne solution dans la plupart des cas . Voir les commentaires sur d'autres réponses, mais le TL; DR est cela APPDATAou LOCALAPPDATAest presque toujours le bon choix, pas USERPROFILE, sous Windows.
Micah Zoltu le