Go library for detecting the user's home directory without cgo
go-homedir is a Go library for detecting the user's home directory without the use of cgo, enabling cross-compilation. It provides functions to get the home directory and expand tilde paths, with built-in caching for performance.
go get github.com/mitchellh/go-homedirimport "github.com/mitchellh/go-homedir"Or with an alias:
import hd "github.com/mitchellh/go-homedir"package main
import (
"fmt"
"log"
"github.com/mitchellh/go-homedir"
)
func main() {
// Get the home directory
dir, err := homedir.Dir()
if err != nil {
log.Fatal(err)
}
fmt.Println("Home directory:", dir)
// Expand a path with tilde
expanded, err := homedir.Expand("~/.config/myapp")
if err != nil {
log.Fatal(err)
}
fmt.Println("Expanded path:", expanded)
}Detects the user's home directory using OS-specific methods without requiring cgo. This enables cross-compilation while maintaining functionality across Windows, macOS, and Unix-like systems.
func Dir() (string, error)Returns the home directory for the executing user. Uses an OS-specific method for discovering the home directory. An error is returned if a home directory cannot be detected.
Detection Strategy:
HOME, USERPROFILE, or HOMEDRIVE+HOMEPATH environment variablesHOME environment variable, falls back to dscl commandHOME environment variable, falls back to getent passwd, then sh -c "cd && pwd"home environment variable (lowercase)Caching: Results are cached by default for performance. Use DisableCache variable or Reset() function to control caching behavior.
Thread Safety: This function is thread-safe and uses mutex locks for cache access.
Example:
dir, err := homedir.Dir()
if err != nil {
log.Fatal("Could not get home directory:", err)
}
fmt.Printf("Home directory: %s\n", dir)Expands paths that are prefixed with ~ to include the home directory. Paths without the tilde prefix are returned unchanged.
func Expand(path string) (string, error)Expands the path to include the home directory if the path is prefixed with ~. If it isn't prefixed with ~, the path is returned as-is.
Parameters:
path string: The path to expand, which may or may not start with ~Returns:
string: The expanded path with the home directory, or the original path if not prefixed with ~error: An error if the home directory cannot be determined, or if user-specific syntax is usedBehavior:
~~/path to {home-dir}/path~username/pathExample:
// Expand a config path
configPath, err := homedir.Expand("~/.config/myapp/settings.json")
if err != nil {
log.Fatal(err)
}
fmt.Println(configPath) // Output: /home/username/.config/myapp/settings.json
// Non-tilde paths are returned unchanged
absolutePath, _ := homedir.Expand("/etc/config")
fmt.Println(absolutePath) // Output: /etc/configClears the cached home directory value, forcing the next call to Dir() to re-detect the home directory. This is primarily useful in testing scenarios.
func Reset()Clears the cache, forcing the next call to Dir() to re-detect the home directory. This generally never has to be called, but can be useful in tests if you're modifying the home directory via the HOME environment variable or other methods.
Thread Safety: This function is thread-safe and uses mutex locks for cache manipulation.
Example:
// Initial call - detects and caches home directory
dir1, _ := homedir.Dir()
// Change HOME environment variable for testing
os.Setenv("HOME", "/tmp/test-home")
// Clear cache to force re-detection
homedir.Reset()
// Next call will use new HOME value
dir2, _ := homedir.Dir()Controls whether the home directory detection result is cached for subsequent calls.
var DisableCache boolDisableCache will disable caching of the home directory. Caching is enabled by default (DisableCache = false).
Default Value: false (caching is enabled)
Behavior:
false (default), the first call to Dir() caches the result for future callstrue, every call to Dir() re-detects the home directoryDir()Example:
// Disable caching for dynamic environments
homedir.DisableCache = true
// Each call will now re-detect the home directory
dir1, _ := homedir.Dir()
os.Setenv("HOME", "/new/home")
dir2, _ := homedir.Dir() // Will detect the new HOME valueThe library returns errors in the following scenarios:
Dir() errors:
HOME, USERPROFILE, HOMEDRIVE, HOMEPATH) are blank or missingExpand() errors:
Dir())~username/path), which returns the error: "cannot expand user-specific home dir"Example error handling:
dir, err := homedir.Dir()
if err != nil {
// Handle the case where home directory cannot be determined
log.Fatal("Failed to get home directory:", err)
}
expanded, err := homedir.Expand("~otheruser/file")
if err != nil {
// This will error: "cannot expand user-specific home dir"
log.Println("Expansion failed:", err)
}