Addacachetoagofunctionasifitwereastaticmember

Say I have an expensive function

func veryExpensiveFunction(int) int

并且这个函数被多次调用同一个号码。

如果再次调用该函数甚至可以为veryExpensiveFunction2 重用,是否有一种好方法可以让该函数存储以前的结果以供使用?

显然,可以添加一个参数

func veryExpensiveFunctionCached(p int, cache map[int]int) int {
    if val, ok := cache[p]; ok {
        return val
    }
    result := veryExpensiveFunction(p)
    cache[p] = result
    return result
}

但是现在我必须在某个地方创建缓存,我不在乎它。如果可能的话,我宁愿将其作为“静态函数成员”。

在 go 中模拟静态成员缓存的好方法是什么?

回答

你可以使用闭包;并让闭包管理缓存。

func InitExpensiveFuncWithCache() func(p int) int {
    var cache = make(map[int]int)
    return func(p int) int {
        if ret, ok := cache[p]; ok {
            fmt.Println("from cache")
            return ret
        }
        // expensive computation
        time.Sleep(1 * time.Second)
        r := p * 2
        cache[p] = r
        return r
    }
}

func main() {
    ExpensiveFuncWithCache := InitExpensiveFuncWithCache()
    
    fmt.Println(ExpensiveFuncWithCache(2))
    fmt.Println(ExpensiveFuncWithCache(2))
}

output:
4
from cache
4

veryExpensiveFunctionCached := InitExpensiveFuncWithCache()

并在您的代码中使用包装函数。你可以在这里试试。

如果您希望它可重用,请将签名更改为,InitExpensiveFuncWithCache(func(int) int)以便它接受一个函数作为参数。将它包裹在闭包中,用它代替昂贵的计算部分。


回答

如果此缓存将用于 http 处理程序,则需要注意同步。在 Go 标准库中,每个 http 请求都在一个专用的 goroutine 中处理,此时我们处于并发和竞争条件的领域。我建议使用RWMutex来确保数据一致性。

至于缓存注入,您可以在创建 http 处理程序的函数中注入它。这是一个原型

type Cache struct {
    store map[int]int
    mux   sync.RWMutex
}

func NewCache() *Cache {
    return &Cache{make(map[int]int), sync.RWMutex{}}
}

func (c *Cache) Set(id, value int) {
    c.mux.Lock()
    c.store[id] = id
    c.mux.Unlock()
}

func (c *Cache) Get(id int) (int, error) {
    c.mux.RLock()
    v, ok := c.store[id]
    c.mux.RUnlock()

    if !ok {
        return -1, errors.New("a value with given key not found")
    }

    return v, nil
}


func handleComplexOperation(c *Cache) http.HandlerFunc {
    return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request){
        
    })
}


以上是Addacachetoagofunctionasifitwereastaticmember的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>