【问题标题】:Obtain user's home directory获取用户的主目录
【发布时间】:2011-12-16 20:39:45
【问题描述】:

以下是获取运行用户主目录的最佳方式吗?还是有我忽略的特定功能?

os.Getenv("HOME")

如果以上是正确的,有没有人碰巧知道这种方法是否可以保证在非 Linux 平台上工作,例如窗户?

【问题讨论】:

  • $HOME 不是必然用户的主目录。例如,我可以在启动你的程序之前写export HOME=/something/else。通常这意味着我出于某种原因想要程序将/something/else 视为我的主目录,并且通常程序应该接受这一点。但如果你真的需要用户的实际主目录,环境变量不一定会给你。

标签: go home-directory


【解决方案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 )
}

【讨论】:

  • 只有我还是只有我在 Windows 上执行此操作需要几秒钟?
  • 在我的 Windows 7 64 位 VM 上看起来绝对是即时的。
  • 请注意,从 go 1.1 开始,“usr, err := user.Current()”将在 osx 上抛出“user: Current not implemented on darwin/amd64”错误。
  • 在交叉编译时不起作用code.google.com/p/go/issues/detail?id=6376
  • 请不要使用这个,改用os.UserHomeDir(),因为它考虑了用户的环境变量和 XDG 基本目录规范!有关详细信息,请参阅下面的答案。
【解决方案2】:

os.UserHomeDir()

在 go1.12+ 中可以使用 os.UserHomeDir()

home, err := os.UserHomeDir()

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

即使没有启用 CGO(即 FROM scratch)也应该可以工作,并且不必解析 /etc/passwd 或其他类似的废话。

【讨论】:

  • 我希望有足够多的人阅读此列表,因为这是应该使用的函数,因为它考虑了用户的环境变量和 XDG 基本目录规范!
  • 如果你使用 os.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)
}

【讨论】:

  • 这与 Jeremy W Sherman 的方法相同,这似乎是目前唯一的方法。非常感谢。
  • 这是 viper util.go userHomeDir()中遵循的方法
  • 在我看到它使用的几乎所有情况下,这不是正确的做法。 USERPROFILE 是系统上用户存储空间的根目录,但它不是应用程序应该在保存对话框提示之外写入的地方。如果您有应用程序配置,则应将其写入APPDATA,如果您有应用程序缓存(或不应通过网络同步的大文件),则应将其写入 Windows 上的LOCALAPPDATA
【解决方案4】:

这是一种简洁的好方法(如果您只在基于 UNIX 的系统上运行):

import (
  "os"
)

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

这只是查询 $HOME 环境变量。

--- 编辑---

我现在看到上面提出了同样的方法。我将把这个例子留在这里作为一个蒸馏解决方案。

【讨论】:

  • 1.之前有人建议过,2.它不是跨平台的,3.接受的答案已经以更好的方式解决了这个问题。
【解决方案5】:

与 @peterSO 类似的答案,但尊重 linux 的 XDG_CONFIG_HOME 路径。

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,因此默认情况下应用程序开发人员不会破坏公司网络。 ?
【解决方案6】:

您应该在 Windows 下使用环境变量 USERPROFILEHOMEPATH。请参阅Recognized Environment Variables(欢迎提供更合适的文档链接)。

【讨论】:

  • 谢谢。那么,您是说 Go 不会为每个平台填充 HOME(它直接委托给 O/S 环境变量),我必须检查每个平台各自的变量以识别主目录?
  • 我查看了源代码,似乎 HOME 没有自动填充。似乎(目前)没有平台无关的工具来获取主目录。
  • @PaulRuane 由于平台使用不同的变量,只需忽略操作系统,检查两个变量,然后选择填充的变量。如果两者都定义了,我会使用HOME,因为这可能意味着你在 cygwin 下运行。
  • 在绝大多数情况下,您应该在 Windows 上使用 USERPROFILEHOMEPATH。在开发人员使用这些的几乎所有情况下,他们应该使用的是APPDATALOCALAPPDATA(取决于登录/注销时通过网络同步内容是否合理)。
  • 改用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)
}

【讨论】:

  • 虽然这个 Go 函数的实现很有趣,但这比使用接受的答案中描述的标准库函数更糟糕。 (并且与六年前 peterSO 的答案相同。)
  • 大多数情况中这不是正确的解决方案。在其他答案上查看 cmets,但 TL;DR 是 APPDATALOCALAPPDATA 在 Windows 上几乎总是正确的选择,而不是 USERPROFILE
猜你喜欢
  • 2021-06-09
  • 2023-03-03
  • 2019-06-20
  • 1970-01-01
  • 2022-10-24
  • 1970-01-01
  • 2017-12-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多