Получить домашний каталог пользователя

#go #home-directory

# #Вперед #домашний каталог

Вопрос:

Является ли следующее лучшим способом получения домашнего каталога запущенного пользователя? Или есть определенная функция, которую я просмотрел?

 os.Getenv("HOME")
 

Если вышесказанное верно, кто-нибудь знает, гарантированно ли этот подход будет работать на платформах, отличных от Linux, например, Windows?

Комментарии:

1. $HOME это не обязательно домашний каталог пользователя. Например, я могу написать export HOME=/something/else перед запуском вашей программы. Обычно это означает, что я по какой-то причине хочу , чтобы программа рассматривалась /something/else как мой домашний каталог, и обычно программа должна это принять. Но если вам действительно нужен фактический домашний каталог пользователя, переменная среды не обязательно предоставит его вам.

Ответ №1:

Начиная с go 1.12, рекомендуемый способ:

 package main
import (
    "os"
    "fmt"
    "log"
)
func main() {
    dirname, err := os.UserHomeDir()
    if err != nil {
        log.Fatal( err )
    }
    fmt.Println( dirname )
}
 

Старая рекомендация:

В go 1.0.3 (возможно, и раньше) работает следующее:

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

Комментарии:

1. Это только я или я единственный, где выполнение этого в Windows занимает несколько секунд?

2. Это определенно кажется мгновенным на моей 64-разрядной виртуальной машине Windows 7.

3. Имейте в виду, что, начиная с go 1.1, «usr, err := user. Current()» выдаст ошибку «user: Current не реализован в darwin / amd64» в osx.

4. не работает при перекрестной компиляции code.google.com/p/go/issues/detail?id=6376

5. Пожалуйста, НЕ ИСПОЛЬЗУЙТЕ ЭТО, используйте os.UserHomeDir() вместо этого, поскольку он учитывает переменные среды пользователя и спецификацию базового каталога XDG! Подробности см. В ответе ниже.

Ответ №2:

os.UserHomeDir()

В go1.12 вы можете использовать ОС.UserHomeDir()

 home, err := os.UserHomeDir()
 

См. https://golang.org/pkg/os/#UserHomeDir

Это должно работать даже без включения CGO (т. Е. FROM scratch ) и без необходимости синтаксического /etc/passwd анализа или другой подобной ерунды.

Комментарии:

1. Я надеюсь, что достаточно людей прочитают этот список, потому что это функция, которую следует использовать, поскольку она учитывает переменные среды пользователя и спецификацию базового каталога XDG!

2. Это было бы еще лучше, если вы используете ОС. UserCacheDir() и os. UserConfigDir(); особенно для людей с домашними каталогами, подобными NFS, или использующих перемещаемые профили и т. Д.

Ответ №3:

Например,

 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. Это тот же подход, что и у Джереми В. Шермана, который, по-видимому, является единственным способом в настоящее время. Большое спасибо.

2. Это подход, применяемый в viper util.go userHomeDir()

3. Почти во всех случаях, когда я вижу, что это используется, это НЕПРАВИЛЬНО . USERPROFILE это корень хранилища пользователя в системе, но это НЕ то место, куда приложения должны записывать вне диалогового окна сохранения. Если у вас есть конфигурация приложения, она должна быть записана APPDATA , и если у вас есть кэш приложения (или большие файлы, которые не должны синхронизироваться по сети), он должен быть записан LOCALAPPDATA в Windows.

Ответ №4:

Вот хороший, краткий способ сделать это (если вы работаете только в системе на базе UNIX):

 import (
  "os"
)

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

Это просто запрашивает переменную среды $HOME.

— Редактировать —

Теперь я вижу, что этот же метод был предложен выше. Я оставлю этот пример здесь в качестве дистиллированного решения.

Комментарии:

1. 1. это было предложено ранее, 2. это не кроссплатформенный, 3. принятый ответ уже решает эту проблему лучшим образом.

Ответ №5:

Аналогичный ответ на @peterSO, но учитывает XDG_CONFIG_HOME путь для 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())
}
 

Комментарии:

1. Хотелось бы, чтобы этот ответ был обновлен и для Windows! APPDATA для конфигурации и LOCALAPPDATA для больших файлов. Для общего назначения «home» я рекомендую LOCALAPPDATA , чтобы разработчики приложений по умолчанию не разрушали корпоративные сети. 😊

Ответ №6:

Вы должны использовать переменную среды USERPROFILE или HOMEPATH под Windows. См. раздел Распознанные переменные среды (приветствуется более подходящая ссылка на документацию).

Комментарии:

1. Спасибо. Значит, вы хотите сказать, что HOME не заполняется Go для каждой платформы (что он делегируется непосредственно в переменные O / S env), и я должен проверять соответствующую переменную каждой платформы, чтобы идентифицировать домашний каталог?

2. Я просмотрел источник, и, похоже, HOME не заполняется автоматически. Кажется, что (в настоящее время) нет независимого от платформы средства для получения домашнего каталога.

3. @PaulRuane Поскольку платформы используют разные переменные, просто игнорируйте ОС, проверяйте обе переменные и выбирайте ту, которая заполнена. Если оба определены, я бы использовал HOME , поскольку это, вероятно, означает, что вы работаете под управлением cygwin.

4. Вы не должны использовать USERPROFILE или HOMEPATH в Windows в подавляющем большинстве случаев. Почти во всех случаях, когда разработчики используют их, они должны использовать APPDATA или LOCALAPPDATA (в зависимости от того, разумно ли синхронизировать содержимое по сети при входе / выходе из системы).

5. Используйте os.UserHomeDir() вместо этого, поскольку он учитывает переменные среды пользователя и спецификацию базового каталога XDG! Подробности см. В ответе ниже.

Ответ №7:

go1.8rc2 имеет функцию go /build/defaultGOPATH, которая получает домашний каталог. https://github.com/golang/go/blob/go1.8rc2/src/go/build/build.go#L260-L277

Следующий код извлекается из функции 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)
}
 

Комментарии:

1. Хотя реализация этой функции Go интересна, это худшее решение, чем использование стандартной библиотечной функции, описанной в принятом ответе. (И это тот же подход, что и ответ петерСО шестилетней давности.)

2. В большинстве случаев это неправильное решение. Смотрите Комментарии к другим ответам, но TL; DR — это APPDATA или LOCALAPPDATA почти всегда правильный выбор, а не USERPROFILE Windows.