Beziehen Sie das Home-Verzeichnis des Benutzers

89

Ist das Folgende der beste Weg, um das Home-Verzeichnis des laufenden Benutzers zu erhalten? Oder gibt es eine bestimmte Funktion, die ich mir angesehen habe?

os.Getenv("HOME")

Wenn das oben Gesagte zutrifft, weiß jemand zufällig, ob dieser Ansatz auf Nicht-Linux-Plattformen, z. B. Windows, garantiert funktioniert?

Paul Ruane
quelle
2
$HOMEist nicht unbedingt das Home-Verzeichnis des Benutzers. Zum Beispiel kann ich schreiben, export HOME=/something/elsebevor ich Ihr Programm starte. Normalerweise bedeutet dies, dass das Programm /something/elseaus irgendeinem Grund als mein Home-Verzeichnis behandelt werden soll , und normalerweise sollte das Programm dies akzeptieren. Aber wenn Sie wirklich die Benutzer benötigen tatsächliches Home - Verzeichnis, wird eine Umgebungsvariable nicht unbedingt gibt es Ihnen.
Keith Thompson
1
@ KeithThompson Danke, aber für meine Zwecke ist es gut genug.
Paul Ruane

Antworten:

173

In go 1.0.3 (wahrscheinlich auch früher) funktioniert Folgendes:

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

Wenn es wichtig ist, übergreifend zu kompilieren, ziehen Sie die Bibliothek in Betrachthomedir

Vlad Didenko
quelle
1
Super, vielen Dank. War sich dieser Änderung nicht bewusst. Genau das habe ich gesucht.
Paul Ruane
Ist es nur ich oder bin ich der einzige, bei dem dies unter Windows einige Sekunden dauert?
Htbaa
Auf meiner Windows 7 64-Bit-VM scheint es definitiv sofort zu sein.
Vlad Didenko
4
Beachten Sie, dass ab go 1.1 "usr, err: = user.Current ()" den Fehler "user: Current not implement on darwin / amd64" auf osx auslöst.
Oleiade
11
funktioniert nicht, wenn cross compiled code.google.com/p/go/issues/detail?id=6376
Vishnu
53

os.UserHomeDir ()

In go1.12 + können Sie os.UserHomeDir () verwenden

home, err := os.UserHomeDir()

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

Das sollte auch ohne CGO-fähig (dh FROM scratch) und ohne Parsen /etc/passwdoder anderen solchen Unsinn funktionieren .

coolaj86
quelle
22

Beispielsweise,

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
quelle
1
Dies ist der gleiche Ansatz wie bei Jeremy W. Sherman, der derzeit der einzige Weg zu sein scheint. Danke vielmals.
Paul Ruane
2
Dies ist der Ansatz in viper util.go userHomeDir ()
RubenLaguna
In fast allen Fällen, in denen ich dies verwendet sehe, ist dies NICHT das Richtige. USERPROFILEist die Wurzel des Speicherplatzes des Benutzers auf dem System, aber NICHT der Ort, an den Anwendungen außerhalb einer Eingabeaufforderung zum Speichern des Dialogfelds schreiben sollten. Wenn Sie über eine Anwendungskonfiguration verfügen, APPDATAsollte diese in LOCALAPPDATAWindows geschrieben werden, und wenn Sie über einen Anwendungscache (oder große Dateien, die nicht über ein Netzwerk synchronisiert werden sollten) verfügen, sollte diese unter Windows beschrieben werden.
Micah Zoltu
4

Hier ist eine schöne, prägnante Möglichkeit (wenn Sie nur auf einem UNIX-basierten System arbeiten):

import (
  "os"
)

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

Das fragt nur die Umgebungsvariable $ HOME ab.

--- Bearbeiten ---

Ich sehe jetzt, dass dieselbe Methode oben vorgeschlagen wurde. Ich werde dieses Beispiel hier als destillierte Lösung belassen.

Murphy Randle
quelle
2
1. Es wurde bereits vorgeschlagen, 2. Es ist nicht plattformübergreifend. 3. Die akzeptierte Antwort löst dieses Problem bereits besser.
Paul Ruane
3

Ähnliche Antwort auf @peterSO, respektiert jedoch den XDG_CONFIG_HOMEPfad für 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
quelle
Ich würde gerne sehen, wie diese Antwort aktualisiert wird, um auch Windows zu respektieren! APPDATAzur Konfiguration und LOCALAPPDATAfür große Dateien. Für ein allgemeines "Zuhause" empfehle ich, LOCALAPPDATAdass Anwendungsentwickler standardmäßig keine Unternehmensnetzwerke zerstören. 😊
Micah Zoltu
2

Sie sollten die Umgebungsvariable USERPROFILEoder HOMEPATHunter Windows verwenden. Siehe Erkannte Umgebungsvariablen (ein ausführlicherer Dokumentationslink wäre zu begrüßen).

Jeremy W. Sherman
quelle
Vielen Dank. Wollen Sie damit sagen, dass HOME nicht für jede Plattform mit Go gefüllt ist (das direkt an die O / S-Umgebungsvariablen delegiert wird), und ich muss die jeweilige Variable jeder Plattform überprüfen, um das Ausgangsverzeichnis zu identifizieren?
Paul Ruane
Ich habe mir die Quelle angesehen und es scheint, dass HOME nicht automatisch ausgefüllt wird. Es scheint (derzeit) keine plattformunabhängige Einrichtung zum Abrufen des Home-Verzeichnisses zu geben.
Paul Ruane
@PaulRuane Da die Plattformen unterschiedliche Variablen verwenden, ignorieren Sie einfach das Betriebssystem, überprüfen Sie beide Variablen und gehen Sie zu dem, was gefüllt ist. Wenn beide definiert sind, würde ich verwenden HOME, da dies wahrscheinlich bedeutet, dass Sie unter Cygwin laufen.
Jeremy W. Sherman
Sie sollten nicht verwenden USERPROFILEoder HOMEPATHunter Windows in der überwiegenden Mehrheit der Fälle. In fast allen Fällen, in denen Entwickler diese verwenden, sollten sie APPDATAoder verwenden LOCALAPPDATA(je nachdem, ob es sinnvoll ist, die Inhalte beim Anmelden / Abmelden über das Netzwerk zu synchronisieren).
Micah Zoltu
2

go1.8rc2 hat die Funktion go / build / defaultGOPATH, die das Home-Verzeichnis abruft. https://github.com/golang/go/blob/go1.8rc2/src/go/build/build.go#L260-L277

Der folgende Code wird aus der defaultGOPATH-Funktion extrahiert.

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
quelle
Die Implementierung dieser Go-Funktion ist zwar interessant, aber eine schlechtere Lösung als die Verwendung der in der akzeptierten Antwort beschriebenen Standardbibliotheksfunktion. (Und ist der gleiche Ansatz wie die Antwort von peterSO vor sechs Jahren.)
Paul Ruane
Dies ist in den meisten Fällen nicht die richtige Lösung . Siehe Kommentare zu anderen Antworten, aber die TL; DR ist das APPDATAoder LOCALAPPDATAist fast immer die richtige Wahl, nicht USERPROFILEunter Windows.
Micah Zoltu