Skip to main content
The go-homedir library detects the home directory using OS-specific methods. This guide explains how it works on different platforms.

How It Works

The Dir() function uses runtime.GOOS to determine the operating system and calls the appropriate platform-specific function:
homedir.go
var result string
var err error
if runtime.GOOS == "windows" {
    result, err = dirWindows()
} else {
    // Unix-like system, so just assume Unix
    result, err = dirUnix()
}

Platform-Specific Behavior

On Windows, the library checks environment variables in this priority order:
  1. HOME - Checked first for compatibility with Unix-like tools
  2. USERPROFILE - The standard Windows environment variable
  3. HOMEDRIVE + HOMEPATH - Fallback combination

Implementation

homedir.go:148-167
func dirWindows() (string, error) {
    // First prefer the HOME environmental variable
    if home := os.Getenv("HOME"); home != "" {
        return home, nil
    }

    // Prefer standard environment variable USERPROFILE
    if home := os.Getenv("USERPROFILE"); home != "" {
        return home, nil
    }

    drive := os.Getenv("HOMEDRIVE")
    path := os.Getenv("HOMEPATH")
    home := drive + path
    if drive == "" || path == "" {
        return "", errors.New("HOMEDRIVE, HOMEPATH, or USERPROFILE are blank")
    }

    return home, nil
}

Error Conditions

An error is returned if all three methods fail:
  • HOME is empty or not set
  • USERPROFILE is empty or not set
  • Either HOMEDRIVE or HOMEPATH is empty or not set
If all environment variables are blank, you’ll get the error: "HOMEDRIVE, HOMEPATH, or USERPROFILE are blank"

Final Fallback

If all platform-specific methods fail, the library falls back to a shell command that works on all Unix-like systems:
homedir.go:132-145
// If all else fails, try the shell
stdout.Reset()
cmd := exec.Command("sh", "-c", "cd && pwd")
cmd.Stdout = &stdout
if err := cmd.Run(); err != nil {
    return "", err
}

result := strings.TrimSpace(stdout.String())
if result == "" {
    return "", errors.New("blank output when reading home directory")
}

return result, nil
This command changes to the home directory and prints the working directory, which is guaranteed to be the home directory.
If even the shell fallback returns blank output, you’ll get the error: "blank output when reading home directory"

Why No CGO?

The library intentionally avoids CGO to:
  • Enable cross-compilation without a C compiler
  • Reduce binary size and complexity
  • Improve build times
  • Avoid CGO-related runtime issues
Instead, it uses Go’s standard library and shell commands, which are available on all target platforms.

Build docs developers (and LLMs) love