go-homedir是一个用于获取用户主目录的微型第三方库,代码不超过200行。源码地址:go-homedir
为什么不用os/user库?
golangos/user
package mainimport ( "fmt" "os/user")func main() { u, _ := user.Current() fmt.Println(u.HomeDir)}
The built-in os/user package requires cgo on Darwin systems. This means that any Go code that uses that package cannot cross compile. But 99% of the time the use for os/user is just to retrieve the home directory, which we can do for the current user without cgo. This library does that, enabling cross-compilation.Darwinos/usercgocgo
接口介绍
go-homedir
DisableCacheboolfalseDir(),Expand()trueDirfunc Dir() (string, error)Expandfunc Expand(path string) (string, error)path~errorResetfunc Reset()
源码分析
Dir
DisableCachefalseDirhomedirCacheResetResetDisableCachetrueReset
var cacheLock sync.RWMutex // 读写锁func Dir() (string, error) { if !DisableCache { // DisableCache为true时,跳过该分支,获取当前主目录 cacheLock.RLock() // 读加锁,禁止其它线程写入,可读 cached := homedirCache cacheLock.RUnlock() if cached != "" { // 第一次或者Reset后第一次cached为空,跳过该分支 return cached, nil } } cacheLock.Lock() // 加锁,禁止其它线程读写 defer cacheLock.Unlock() var result string var err error if runtime.GOOS == "windows" { result, err = dirWindows() // 获取Windows系统主目录 } else { result, err = dirUnix() // 获取Unix-like系统主目录 } if err != nil { return "", err } homedirCache = result // 获取的主目录存入缓存,DisableCache为false后,再次获取主目录直接从缓存读取 return result, nil}
ExpandDIrDir
func Expand(path string) (string, error) { if len(path) == 0 { return path, nil } if path[0] != '~' { return path, nil // } if len(path) > 1 && path[1] != '/' && path[1] != '\\' { return "", errors.New("cannot expand user-specific home dir") } dir, err := Dir() if err != nil { return "", err } return filepath.Join(dir, path[1:]), nil}
ResethomedirCache
func Reset() { cacheLock.Lock() defer cacheLock.Unlock() homedirCache = ""}