获取用户的主目录


89

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

os.Getenv("HOME")

如果上述正确,那么是否有人知道这种方法是否可以保证在非Linux平台(例如Windows)上运行?


2
$HOME并不一定是用户的主目录。例如,我可以export HOME=/something/else在启动程序之前编写。通常,这意味着出于某种原因,我希望程序将其/something/else视为主目录,并且程序通常应该接受它。但是,如果您确实需要用户的实际主目录,则不一定要使用环境变量。
基思·汤普森

1
@KeithThompson谢谢,但出于我的目的,这已经足够了。
Paul Ruane

Answers:


173

在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
太好了,非常感谢。没有意识到这一变化。这正是我想要的。
保罗·鲁安

是我还是我唯一在Windows上花费几秒钟的时间?
Htbaa 2013年

在我的Windows 7 64位VM上,这似乎绝对是即时的。
弗拉德·迪登科

4
请注意,从1.1版开始,osx上将出现“ user:err:= user.Current()”错误。
Oleiade


55

os.UserHomeDir()

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

home, err := os.UserHomeDir()

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

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


22

例如,

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
这与Jeremy W Sherman的方法相同,后者似乎是目前的唯一方法。非常感谢。
Paul Ruane

2
这是毒蛇util.go userHomeDir()中
RubenLaguna

在几乎所有使用此功能的情况下,这都不是正确的选择。 USERPROFILE是用户在系统上存储空间的根,但不是应将应用程序写入保存对话框提示之外的地方。如果您有应用程序配置,则应将其写入APPDATA;如果您有应用程序缓存(或不应通过网络同步的大文件),则应LOCALAPPDATA在Windows上将其写入。
Micah Zoltu

4

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

import (
  "os"
)

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

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

-编辑-

我现在看到上面建议了相同的方法。我将在此示例中以蒸馏溶液的形式保留。


2
1.之前曾有人提出过建议; 2.不是跨平台的; 3.公认的答案已经可以更好地解决此问题。
Paul Ruane 2013年

3

@peterSO的答案类似,但是尊重XDG_CONFIG_HOMElinux 的路径。

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这样做,因此默认情况下,应用程序开发人员不会破坏公司网络。😊
弥Zoltu

2

您应该使用环境变量USERPROFILEHOMEPATH在Windows下使用。请参阅公认的环境变量(欢迎访问更多apropos文档链接)。


谢谢。那么,您是不是在说每个平台的Go都不会填充HOME(它将直接委派给O / S环境变量),而我必须检查每个平台的相应变量以标识主目录?
Paul Ruane

我查看了源,它似乎未自动填充HOME。似乎(当前)没有平台不可知的工具来获取主目录。
Paul Ruane

@PaulRuane由于平台使用不同的变量,因此只需忽略操作系统,检查两个变量,然后使用填充的变量即可。如果两者都定义,我将使用HOME,因为这可能意味着您正在cygwin下运行。
杰里米·W·谢尔曼

您应使用USERPROFILEHOMEPATH在绝大多数情况下,在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

以下代码是从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的回答是相同的。)
Paul Ruane

大多数情况下,这不是正确的解决方案。请参阅有关其他答案的评论,但是TL; DR是Windows上的,APPDATA或者LOCALAPPDATA几乎总是正确的选择,而不是USERPROFILE
Micah Zoltu
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.