Dapatkan direktori home pengguna

94

Apakah berikut cara terbaik untuk mendapatkan direktori home pengguna yang sedang berjalan? Atau adakah fungsi tertentu yang telah saya lihat?

os.Getenv("HOME")

Jika hal di atas benar, adakah yang kebetulan mengetahui apakah pendekatan ini dijamin bekerja pada platform non-Linux, misalnya Windows?

Paul Ruane
sumber
2
$HOMEbelum tentu direktori home pengguna. Misalnya, saya bisa menulis export HOME=/something/elsesebelum meluncurkan program Anda. Biasanya itu berarti saya ingin program diperlakukan /something/elsesebagai direktori home saya karena alasan tertentu, dan biasanya program harus menerimanya. Tetapi jika Anda benar-benar membutuhkan direktori home sebenarnya dari pengguna , variabel lingkungan tidak akan selalu memberikannya kepada Anda.
Keith Thompson
1
@Keompson Terima kasih, tetapi untuk tujuan saya itu cukup baik.
Paul Ruane

Jawaban:

176

Dalam go 1.0.3 (mungkin lebih awal, juga) bekerja berikut:

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

Jika penting untuk cross-kompilasi, pertimbangkan yang homedirperpustakaan

Vlad Didenko
sumber
1
Luar biasa, terima kasih banyak. Tidak menyadari perubahan ini. Inilah yang saya cari.
Paul Ruane
Apakah hanya saya atau saya satu-satunya yang melakukan ini di Windows membutuhkan waktu beberapa detik?
Htbaa
Tampaknya instan di VM Windows 7 64bit saya.
Vlad Didenko
4
Ketahuilah bahwa mulai 1.1, "usr, err: = user.Current ()" akan memunculkan kesalahan "pengguna: Saat ini tidak diterapkan pada darwin / amd64" di osx.
Oleiade
11
tidak berfungsi ketika kode yang
Wisnu
61

os.UserHomeDir ()

Di go1.12 + Anda dapat menggunakan os.UserHomeDir ()

home, err := os.UserHomeDir()

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

Itu harus bekerja bahkan tanpa CGO diaktifkan (yaitu FROM scratch) dan tanpa harus mengurai /etc/passwdatau omong kosong semacam itu.

coolaj86
sumber
23

Sebagai contoh,

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
sumber
1
Ini adalah pendekatan yang sama dengan Jeremy W. Sherman yang tampaknya menjadi satu-satunya cara saat ini. Terimakasih banyak.
Paul Ruane
2
Ini adalah pendekatan yang diikuti di viper util.go userHomeDir ()
RubenLaguna
Dalam hampir semua kasus di mana saya melihat ini digunakan, ini BUKAN hal yang benar untuk dilakukan. USERPROFILEadalah root dari ruang penyimpanan Pengguna di sistem, tetapi BUKAN tempat di mana aplikasi harus menulis di luar prompt dialog simpan. Jika Anda memiliki konfigurasi aplikasi, konfigurasi tersebut harus ditulis ke APPDATAdan jika Anda memiliki cache aplikasi (atau file besar yang tidak boleh disinkronkan melalui jaringan) , konfigurasi tersebut harus ditulis LOCALAPPDATAdi Windows.
Mikha Zoltu
4

Berikut adalah cara yang bagus dan ringkas untuk melakukannya (jika Anda hanya menjalankan sistem berbasis UNIX):

import (
  "os"
)

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

Itu hanya menanyakan variabel lingkungan $ HOME.

--- Edit ---

Sekarang saya melihat bahwa metode yang sama disarankan di atas. Saya akan meninggalkan contoh ini di sini sebagai solusi suling.

Murphy Randle
sumber
2
1. sudah disarankan sebelumnya, 2. bukan lintas platform, 3. jawaban yang diterima sudah menyelesaikan masalah ini dengan cara yang lebih baik.
Paul Ruane
3

Jawaban serupa untuk @peterSO tetapi menghormati XDG_CONFIG_HOMEjalur untuk 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
sumber
Akan sangat senang melihat jawaban ini diperbarui untuk menghormati Windows juga! APPDATAuntuk konfigurasi dan LOCALAPPDATAuntuk file besar. Untuk tujuan umum "rumah", saya sarankan LOCALAPPDATAagar secara default pengembang aplikasi tidak merusak jaringan perusahaan. 😊
Mikha Zoltu
2

Anda harus menggunakan variabel lingkungan USERPROFILEatau di HOMEPATHbawah Windows. Lihat Variabel Lingkungan yang Diakui (tautan dokumentasi yang lebih tepat akan disambut).

Jeremy W. Sherman
sumber
Terima kasih. Apakah Anda mengatakan, bahwa HOME tidak diisi oleh Go untuk setiap platform (yang didelegasikan langsung ke dalam O / S env vars) dan saya harus memeriksa variabel masing-masing platform untuk mengidentifikasi direktori home?
Paul Ruane
Saya telah melihat sumbernya dan tampaknya HOME tidak terisi secara otomatis. Sepertinya (saat ini) tidak ada fasilitas agnostik platform untuk mendapatkan direktori home.
Paul Ruane
@PaulRuane Karena platform menggunakan variabel yang berbeda, abaikan saja OS, periksa kedua variabel, dan gunakan variabel mana saja yang terisi. Jika keduanya didefinisikan, saya akan menggunakan HOME, karena itu mungkin berarti Anda menjalankan cygwin.
Jeremy W. Sherman
Anda TIDAK boleh menggunakan USERPROFILEatau HOMEPATHdi Windows dalam sebagian besar kasus. Dalam hampir semua kasus di mana devs menggunakan itu, apa yang seharusnya mereka gunakan adalah APPDATAatau LOCALAPPDATA(tergantung pada apakah konten tersebut masuk akal untuk disinkronkan melalui jaringan saat login / logout).
Mikha Zoltu
2

go1.8rc2 memiliki fungsi go / build / defaultGOPATH yang mendapatkan direktori home. https://github.com/golang/go/blob/go1.8rc2/src/go/build/build.go#L260-L277

Kode berikut diekstrak dari fungsi 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
sumber
Meskipun penerapan fungsi Go ini menarik, ini adalah solusi yang lebih buruk daripada menggunakan fungsi pustaka standar yang dijelaskan dalam jawaban yang diterima. (Dan merupakan pendekatan yang sama dengan jawaban peterSO dari enam tahun lalu.)
Paul Ruane
Ini bukanlah solusi yang tepat dalam banyak kasus . Lihat komentar di jawaban lain, tetapi TL; DR adalah itu APPDATAatau LOCALAPPDATAhampir selalu merupakan pilihan yang tepat, bukan USERPROFILE, di Windows.
Mikha Zoltu