package memo import "sync" type Func func(key interface{}) interface{} type result struct { value interface{} } type Memo struct { f Func cache map[interface{}]result mu sync.RWMutex // Allows concurrent reads. } func New(f Func) *Memo { return &Memo{ f: f, cache: make(map[interface{}]result), } } func (memo *Memo) Get(key interface{}) interface{} { // First, try to read the cache using a read lock. memo.mu.RLock() res, ok := memo.cache[key] memo.mu.RUnlock() if ok { return res.value } // Compute the result without holding the lock. computed := memo.f(key) // Now acquire a write lock to update the cache. memo.mu.Lock() // Double-check: another goroutine may have stored the result in the meantime. res, ok = memo.cache[key] if !ok { res.value = computed memo.cache[key] = res } memo.mu.Unlock() return res.value }