diff --git a/src/os/user/lookup.go b/src/os/user/lookup.go index 3b4421badd5..2243a25788a 100644 --- a/src/os/user/lookup.go +++ b/src/os/user/lookup.go @@ -4,20 +4,40 @@ package user +import "sync" + // Current returns the current user. func Current() (*User, error) { - return current() + cache.Do(func() { cache.u, cache.err = current() }) + if cache.err != nil { + return nil, cache.err + } + u := *cache.u // copy + return &u, nil +} + +// cache of the current user +var cache struct { + sync.Once + u *User + err error } // Lookup looks up a user by username. If the user cannot be found, the // returned error is of type UnknownUserError. func Lookup(username string) (*User, error) { + if u, err := Current(); err == nil && u.Username == username { + return u, err + } return lookupUser(username) } // LookupId looks up a user by userid. If the user cannot be found, the // returned error is of type UnknownUserIdError. func LookupId(uid string) (*User, error) { + if u, err := Current(); err == nil && u.Uid == uid { + return u, err + } return lookupUserId(uid) } diff --git a/src/os/user/user_test.go b/src/os/user/user_test.go index 9d8d94d8dae..73e8ed8de73 100644 --- a/src/os/user/user_test.go +++ b/src/os/user/user_test.go @@ -31,6 +31,12 @@ func TestCurrent(t *testing.T) { } } +func BenchmarkCurrent(b *testing.B) { + for i := 0; i < b.N; i++ { + Current() + } +} + func compare(t *testing.T, want, got *User) { if want.Uid != got.Uid { t.Errorf("got Uid=%q; want %q", got.Uid, want.Uid)