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 = ""}