3 回答

TA贡献1859条经验 获得超6个赞
您可以使用闭包;并让闭包管理缓存。
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)

TA贡献1812条经验 获得超5个赞
如果要在 http 处理程序中使用此缓存,则需要小心同步。在 Go 标准 lib 中,每个 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){
})
}

TA贡献1802条经验 获得超6个赞
Go 标准库使用以下样式来提供“静态”函数(例如,标志。命令行),但利用基础状态:
// "static" function is just a wrapper
func Lookup(p int) int { return expCache.Lookup(p) }
var expCache = NewCache()
func newCache() *CacheExpensive { return &CacheExpensive{cache: make(map[int]int)} }
type CacheExpensive struct {
l sync.RWMutex // lock for concurrent access
cache map[int]int
}
func (c *CacheExpensive) Lookup(p int) int { /*...*/ }
这种设计模式不仅允许简单的一次性使用,而且还允许隔离使用:
var (
userX = NewCache()
userY = NewCache()
)
userX.Lookup(12)
userY.Lookup(42)
- 3 回答
- 0 关注
- 138 浏览
添加回答
举报