我如何概括这个 map + sync.RWMutex 模式?

How can I generalize this map + sync.RWMutex pattern?

考虑到 go 中没有泛型,我如何概括这个映射 access/modification 模式?

func (pool *fPool) fetch(url string) *ResultPromise {
    pool.cacheLock.RLock()
    if rp, pres := pool.cache[url]; pres {
        pool.cacheLock.RUnlock()
        return rp
    }
    pool.cacheLock.RUnlock()
    pool.cacheLock.Lock()
    if rp, pres := pool.cache[url]; pres {
        pool.cacheLock.Unlock()
        // Skip adding url if someone snuck it in between RUnlock an Lock
        return rp
    }
    rp := newPromise()
    pool.cache[url] = rp
    pool.cacheLock.Unlock()
    pool.c <- fetchWork{rp, url} // Expensive/atomic work
    return rp
}

出于显而易见的原因,它用于多个不同类型的地图。

也许这是一个糟糕的解决方案?

免责声明:这与 中的代码相同,抱歉。

既然泛型可用,我决定重新访问 Go,并回答我的问题。这是我想出的:

type Cached[K comparable, R any] struct {
    cache map[K]R
    fn    func(K) R
    lock  sync.RWMutex
}

func NewCached[K comparable, R any](
    fn func(K) R) *Cached[K, R] {
    return &Cached[K, R]{
        cache: make(map[K]R),
        fn:    fn,
        lock:  sync.RWMutex{},
    }
}

func (c *Cached[K, R]) Get(k K) R {
    c.lock.RLock()
    if rp, pres := c.cache[k]; pres {
        c.lock.RUnlock()
        return rp
    }
    c.lock.RUnlock()
    c.lock.Lock()
    defer c.lock.Unlock()
    if rp, pres := c.cache[k]; pres {
        // Skip adding key if someone else snuck it in between RUnlock and Lock
        return rp
    }
    rp := c.fn(k)
    c.cache[k] = rp
    return rp
}

游乐场
(目前链接到 ?v=gotip 但未发布,因为泛型仍未发布或其他原因?idk)

previous