#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.