Отримати домашній каталог користувача


92

Чи є наступний найкращий спосіб отримати домашній каталог запущеного користувача? Або є певна функція, яку я вже розробив?

os.Getenv("HOME")

Якщо вищезазначене правильно, чи хтось випадково знає, чи гарантовано такий підхід буде працювати на платформах, що не належать до Linux, наприклад, Windows?


2
$HOMEне обов’язково домашній каталог користувача. Наприклад, я можу написати export HOME=/something/elseперед запуском вашої програми. Зазвичай це означає, що я хочу, щоб програма з /something/elseякихось причин сприймалася як мій домашній каталог, і зазвичай програма повинна це прийняти. Але якщо вам дійсно потрібен користувач фактичного домашнього каталог, змінна оточення не обов'язково давати його вам.
Кіт Томпсон,

1
@KeithThompson Дякую, але для моїх цілей це досить добре.
Paul Ruane,

Відповіді:


175

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

Якщо це важливо для крос-компіляції, розглянемо в homedirбібліотеку


1
Чудово, велике спасибі. Не знав про цю зміну. Це саме те, що я шукав.
Paul Ruane,

Це лише я чи я єдиний, де це робиться у Windows триває кілька секунд?
Htbaa

Це однозначно здається миттєвим на моїй 64-бітній віртуальній машині Windows 7.
Влад Діденко

4
Майте на увазі, що починаючи з версії 1.1, "usr, err: = user.Current ()" видасть помилку "user: Current не реалізований на darwin / amd64" на osx.
Oleiade

11
не працює при перехресному компілюванні code.google.com/p/go/issues/detail?id=6376
Вішну

59

os.UserHomeDir ()

У go1.12 + ви можете використовувати os.UserHomeDir ()

home, err := os.UserHomeDir()

Див. Https://golang.org/pkg/os/#UserHomeDir

Це повинно працювати навіть без увімкненої CGO (тобто FROM scratch) і без необхідності аналізу /etc/passwdчи інших подібних дурниць.


23

Наприклад,

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
Це той самий підхід, що і Джеремі Шерман, який на сьогодні є єдиним способом. Дуже дякую.
Paul Ruane,

2
Це підхід, використаний у viper util.go userHomeDir ()
RubenLaguna

Майже у всіх випадках, коли я бачу, що це використовується, це НЕ правильно робити. USERPROFILEє коренем простору пам’яті Користувача в системі, але це НЕ місце, куди додатки повинні писати за межами запиту діалогового вікна збереження. Якщо у вас є конфігурація програми, її слід записати, APPDATAа якщо у вас кеш програми (або великі файли, які не повинні синхронізуватися через мережу), її слід записати в LOCALAPPDATAWindows.
Micah Zoltu

4

Ось приємний, стислий спосіб це зробити (якщо ви працюєте лише в системі на основі UNIX):

import (
  "os"
)

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

Це просто запитує змінну середовища $ HOME.

--- Редагувати ---

Тепер я бачу, що цей самий метод був запропонований вище. Цей приклад я залишу тут як дистильований розчин.


2
1. це пропонувалося раніше, 2. це не крос-платформа, 3. прийнята відповідь вже вирішує цю проблему кращим чином.
Paul Ruane,

3

Відповідь подібна до @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())
}

Хотілося б побачити цю відповідь оновленою, щоб також поважати Windows! APPDATAдля конфігурації та LOCALAPPDATAдля великих файлів. Для загального призначення "домашній" я рекомендую, LOCALAPPDATAщоб за замовчуванням розробники додатків не руйнували корпоративні мережі. 😊
Михей Золту

2

Вам слід використовувати змінну середовища USERPROFILEабо HOMEPATHпід Windows. Див. Визнані змінні навколишнього середовища (вітається відповідне посилання на документацію).


Дякую. Ви тоді говорите, що HOME не заповнюється Go для кожної платформи (що він делегує безпосередньо в O / S env vars), і я повинен перевірити відповідну змінну кожної платформи, щоб визначити домашній каталог?
Пол Руан,

Я подивився джерело, і, схоже, HOME не заповнюється автоматично. Здається, що (на даний момент) немає агностичного засобу платформи для отримання домашнього каталогу.
Paul Ruane,

@PaulRuane Оскільки платформи використовують різні змінні, просто ігноруйте ОС, перевіряйте обидві змінні та йдіть із тим, що із заповнених. Якщо обидва визначені, я б використав HOME, оскільки це, мабуть, означає, що ви працюєте під cygwin.
Джеремі В. Шерман,

Вам НЕ слід користуватися USERPROFILEабо HOMEPATHна Windows у переважній більшості випадків. Практично у всіх випадках, коли розробники використовують їх, те, що вони повинні використовувати, це ( APPDATAабо LOCALAPPDATAзалежно від того, чи є доцільним синхронізація вмісту через мережу під час входу / виходу).
Micah Zoltu

2

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

Наступний код витягується із функції GOPATH за замовчуванням.

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

Хоча реалізація цієї функції Go є цікавою, це гірше рішення, ніж використання стандартної функції бібліотеки, описаної у прийнятій відповіді. (І такий самий підхід, як відповідь peterSO від шести років тому.)
Пол Руан,

У більшості випадків це не правильне рішення . Дивіться коментарі на інші відповіді, але TL; DR, що APPDATAабо LOCALAPPDATAмайже завжди правильний вибір, а НЕ USERPROFILEна Windows.
Micah Zoltu
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.