Kullanıcının ana dizinini edinin


94

Aşağıdaki, çalışan kullanıcının ana dizinini elde etmenin en iyi yolu mudur? Yoksa dikkatimi çeken belirli bir işlev mi var?

os.Getenv("HOME")

Yukarıdakiler doğruysa, bu yaklaşımın Linux dışı platformlarda, örneğin Windows'ta çalışmasının garanti edilip edilmediğini bilen var mı?


2
$HOMEdeğil mutlaka kullanıcının ev dizini. Örneğin, export HOME=/something/elseprogramınızı başlatmadan önce yazabilirim . Genellikle bu , programın herhangi bir nedenle ana dizinim olarak işlemesini istediğim anlamına gelir /something/elseve genellikle program bunu kabul etmelidir. Ancak kullanıcının gerçek ana dizinine gerçekten ihtiyacınız varsa , bir ortam değişkeni onu size mutlaka vermeyecektir.
Keith Thompson

1
@KeithThompson Teşekkürler ama benim amacım için yeterince iyi.
Paul Ruane 2811

Yanıtlar:


175

Go 1.0.3'te (muhtemelen daha önce de) aşağıdakiler çalışır:

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

Çapraz derlemek önemliyse , kütüphaneyi düşününhomedir


1
Harika, çok teşekkürler. Bu değişikliğin farkında değildim. Bu tam olarak aradığım şeydi.
Paul Ruane

Sadece ben miyim yoksa bunu Windows'ta yapmanın birkaç saniye sürdüğü tek kişi ben miyim?
Htbaa

Windows 7 64bit VM'mde kesinlikle anında görünüyor.
Vlad Didenko

4
Unutmayın ki 1.1, "usr, err: = user.Current ()", osx'te bir "user: darwin / amd64 üzerinde gerçeklenmemiş" hatası atacaktır.
Oleiade

11
çapraz derlendiğinde çalışmıyor code.google.com/p/go/issues/detail?id=6376
Vishnu

61

os.UserHomeDir ()

Go1.12 + 'da os.UserHomeDir () kullanabilirsiniz.

home, err := os.UserHomeDir()

Bkz. Https://golang.org/pkg/os/#UserHomeDir

Bu, CGO etkinleştirilmeden (yani FROM scratch) ve ayrıştırmaya /etc/passwdveya benzeri saçmalıklara gerek kalmadan çalışmalıdır .


23

Örneğin,

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
Bu, şu anda tek yol gibi görünen Jeremy W Sherman ile aynı yaklaşımdır. Çok teşekkürler.
Paul Ruane 2811

2
Bu, viper util.go'da izlenen yaklaşımdır userHomeDir ()
RubenLaguna 01

Bunun kullanıldığını gördüğüm neredeyse tüm durumlarda, bu yapılacak doğru şey DEĞİL . USERPROFILEKullanıcının sistemdeki depolama alanının köküdür, ancak uygulamaların bir kaydetme iletişim kutusu isteminin dışına yazması gereken yer DEĞİLDİR . Uygulama yapılandırmanız varsa, buna yazılmalı APPDATAve uygulama önbelleğiniz varsa (veya bir ağ üzerinden eşitlenmemesi gereken büyük dosyalarınız varsa) LOCALAPPDATAWindows'ta yazılmalıdır .
Micah Zoltu

4

İşte bunu yapmanın güzel ve özlü bir yolu (yalnızca UNIX tabanlı bir sistemde çalışıyorsanız):

import (
  "os"
)

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

Bu sadece $ HOME ortam değişkenini sorgular.

--- Düzenle ---

Şimdi aynı yöntemin yukarıda önerildiğini görüyorum. Bu örneği burada damıtılmış bir çözüm olarak bırakacağım.


2
1. daha önce önerildi, 2. platformlar arası değil, 3. Kabul edilen yanıt bu sorunu daha iyi bir şekilde çözüyor.
Paul Ruane

3

@PeterSO'ya benzer cevap ama XDG_CONFIG_HOMElinux için yola saygı duyuyor .

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

Bu cevabın Windows'a da saygı duyacak şekilde güncellendiğini görmek isterim! APPDATAyapılandırma ve LOCALAPPDATAbüyük dosyalar için. Genel amaçlı bir "ev" LOCALAPPDATAiçin, varsayılan olarak uygulama geliştiricilerinin kurumsal ağları bozmamasını öneririm . 😊
Micah Zoltu

2

Ortam değişkenini USERPROFILEveya HOMEPATHWindows altında kullanmalısınız . Tanınan Ortam Değişkenlerine bakın (daha uygun bir dokümantasyon bağlantısı memnuniyetle karşılanacaktır).


Teşekkürler. Öyleyse, HOME'un her platform için Go tarafından doldurulmadığını (doğrudan O / S ortam değişkenlerine delege ettiğini) ve ana dizini tanımlamak için her platformun ilgili değişkenini kontrol etmem gerektiğini mi söylüyorsunuz?
Paul Ruane

Kaynağa bir göz attım ve HOME'un otomatik olarak doldurulmadığı görülüyor. Ana dizini elde etmek için (şu anda) platformdan bağımsız bir tesis yok gibi görünüyor.
Paul Ruane

@PaulRuane Platformlar farklı değişkenler kullandığından, sadece işletim sistemini yok sayın, her iki değişkeni de kontrol edin ve hangisi doluysa oraya gidin. Her ikisi de tanımlanmışsa, kullanırım HOMEçünkü bu muhtemelen cygwin altında çalıştığınız anlamına gelir.
Jeremy W. Sherman

Sen olmalıdır DEĞİL kullanmak USERPROFILEveya HOMEPATHvakaların büyük çoğunluğunda Windows üzerinde. Geliştiricilerin bunları kullandığı hemen hemen tüm durumlarda, kullanmaları gereken şey APPDATAveya LOCALAPPDATA(içeriğin giriş / çıkış sırasında ağ üzerinden senkronize edilmesinin makul olup olmamasına bağlı olarak).
Micah Zoltu

2

go1.8rc2, ana dizini alan go / build / defaultGOPATH işlevine sahiptir. https://github.com/golang/go/blob/go1.8rc2/src/go/build/build.go#L260-L277

Aşağıdaki kod, defaultGOPATH işlevinden alınmıştır.

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

Bu Go işlevinin uygulanması ilginç olsa da, bu, kabul edilen yanıtta açıklanan standart kitaplık işlevini kullanmaktan daha kötü bir çözümdür. (Ve peterSO'nun altı yıl önceki cevabı ile aynı yaklaşım.)
Paul Ruane

Çoğu durumda bu doğru çözüm değildir . Diğer cevaplar ilgili yorum ancak TL Bkz; DR yani APPDATAya LOCALAPPDATAdeğil, hemen hemen her zaman doğru seçimdir USERPROFILEWindows üzerinde.
Micah Zoltu
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.