Uzyskaj katalog domowy użytkownika


94

Czy poniższy sposób jest najlepszym sposobem uzyskania katalogu domowego uruchomionego użytkownika? A może jest jakaś konkretna funkcja, którą przejrzałem?

os.Getenv("HOME")

Jeśli powyższe jest poprawne, to czy ktoś wie, czy takie podejście gwarantuje działanie na platformach innych niż Linux, np. Windows?


2
$HOMENie jest koniecznie katalog domowy użytkownika. Na przykład mogę pisać export HOME=/something/elseprzed uruchomieniem programu. Zwykle oznacza to, że chcę, aby program z /something/elsejakiegoś powodu traktował jako mój katalog domowy i zwykle program powinien to zaakceptować. Ale jeśli naprawdę potrzebujesz użytkownika rzeczywisty katalog domowy, zmienna środowiskowa nie musi ci go.
Keith Thompson

1
@KeithThompson Dzięki, ale dla moich celów jest wystarczająco dobre.
Paul Ruane

Odpowiedzi:


176

W go 1.0.3 (prawdopodobnie również wcześniej) działa:

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

Jeśli ważne jest cross-kompilacji, należy rozważyć z homedirbiblioteki


1
Super, wielkie dzięki. Nie był świadomy tej zmiany. To jest dokładnie to, czego szukałem.
Paul Ruane

Czy to tylko ja, czy jestem jedyną osobą, w której robienie tego w systemie Windows zajmuje kilka sekund?
Htbaa

Zdecydowanie wydaje się to natychmiastowe na mojej 64-bitowej maszynie wirtualnej Windows 7.
Vlad Didenko

4
Należy pamiętać, że od wersji 1.1, "usr, err: = user.Current ()" wyświetli na osx błąd "user: Current not zaimplementowany w darwin / amd64".
Oleiade,

11
nie działa, gdy skompilowano krzyżowo code.google.com/p/go/issues/detail?id=6376
Wisznu

61

os.UserHomeDir ()

W go1.12 + możesz użyć os.UserHomeDir ()

home, err := os.UserHomeDir()

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

To powinno działać nawet bez włączonego CGO (tj. FROM scratch) I bez konieczności analizowania /etc/passwdlub innych takich bzdur.


23

Na przykład,

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)
}

1
To jest to samo podejście, co Jeremy W. Sherman, które wydaje się być obecnie jedynym sposobem. Wielkie dzięki.
Paul Ruane

2
To jest podejście zastosowane w viper util.go userHomeDir ()
RubenLaguna

W prawie wszystkich przypadkach, w których widzę to używane, NIE jest to właściwe. USERPROFILEto katalog główny przestrzeni dyskowej użytkownika w systemie, ale NIE jest to miejsce, w którym aplikacje powinny zapisywać dane poza oknem dialogowym zapisywania. Jeśli masz konfigurację aplikacji, powinna być zapisana, APPDATAa jeśli masz pamięć podręczną aplikacji (lub duże pliki, które nie powinny być synchronizowane przez sieć), powinna zostać zapisana LOCALAPPDATAw systemie Windows.
Micah Zoltu

4

Oto ładny, zwięzły sposób na zrobienie tego (jeśli używasz tylko systemu opartego na UNIX):

import (
  "os"
)

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

To tylko odpytuje zmienną środowiskową $ HOME.

--- Edytować ---

Teraz widzę, że ta sama metoda została zasugerowana powyżej. Zostawię ten przykład jako roztwór destylowany.


2
1. to sugerowano wcześniej, 2. nie jest to platforma wieloplatformowa, 3. zaakceptowana odpowiedź już rozwiązuje ten problem w lepszy sposób.
Paul Ruane

3

Podobna odpowiedź do @peterSO, ale szanuje XDG_CONFIG_HOMEścieżkę dla Linuksa.

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())
}

Chciałbym, aby ta odpowiedź została zaktualizowana, aby szanować również system Windows! APPDATAdo konfiguracji i LOCALAPPDATAdużych plików. Dla ogólnego przeznaczenia polecam, LOCALAPPDATAaby twórcy aplikacji domyślnie nie niszczyli sieci korporacyjnych. 😊
Micah Zoltu

2

Powinieneś użyć zmiennej środowiskowej USERPROFILElub HOMEPATHw systemie Windows. Zobacz Rozpoznane zmienne środowiskowe (mile widziany byłby link do bardziej odpowiedniej dokumentacji).


Dzięki. Czy chcesz powiedzieć, że HOME nie jest zapełniane przez Go dla każdej platformy (która deleguje bezpośrednio do zmiennych środowiska O / S) i muszę sprawdzić odpowiednią zmienną każdej platformy, aby zidentyfikować katalog domowy?
Paul Ruane

Przyjrzałem się źródłu i wygląda na to, że HOME nie jest automatycznie wypełniane. Wygląda na to, że nie ma (obecnie) narzędzia niezależnego od platformy do uzyskiwania katalogu domowego.
Paul Ruane

@PaulRuane Ponieważ platformy używają różnych zmiennych, po prostu zignoruj ​​system operacyjny, sprawdź obie zmienne i wybierz tę, która jest zapełniona. Jeśli oba są zdefiniowane, użyłbym HOME, ponieważ prawdopodobnie oznacza to, że biegasz pod cygwin.
Jeremy W. Sherman

W większości przypadków NIE powinieneś używać USERPROFILEani HOMEPATHw systemie Windows. W prawie wszystkich przypadkach, w których deweloperzy ich używają, powinni używać APPDATAlub LOCALAPPDATA(w zależności od tego, czy rozsądna jest synchronizacja zawartości przez sieć podczas logowania / wylogowywania).
Micah Zoltu

2

go1.8rc2 ma funkcję go / build / defaultGOPATH, która pobiera katalog domowy. https://github.com/golang/go/blob/go1.8rc2/src/go/build/build.go#L260-L277

Poniższy kod jest wyodrębniany z funkcji 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)
}

O ile realizacja tej funkcji Go jest interesująca, jest to gorsze rozwiązanie niż użycie standardowej funkcji bibliotecznej opisanej w zaakceptowanej odpowiedzi. (I jest to to samo podejście, co odpowiedź peterSO sprzed sześciu lat.)
Paul Ruane

W większości przypadków nie jest to właściwe rozwiązanie . Zobacz komentarze do innych odpowiedzi, ale TL; DR jest tym APPDATAlub LOCALAPPDATAprawie zawsze jest właściwym wyborem, a nie USERPROFILEw systemie Windows.
Micah Zoltu
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.