亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

將緩存添加到 go 函數中,就好像它是靜態成員一樣

將緩存添加到 go 函數中,就好像它是靜態成員一樣

Go
ITMISS 2022-09-05 10:14:38
假設我有一個昂貴的功能func veryExpensiveFunction(int) int并且對于相同的數字,此函數被調用很多。有沒有一種好方法可以允許這個函數存儲以前的結果,以便在再次調用該函數時使用,甚至可能對非常消耗的函數2重用?顯然,可以添加一個參數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 中模擬靜態成員緩存的好方法是什么?
查看完整描述

3 回答

?
慕絲7291255

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)


查看完整回答
反對 回復 2022-09-05
?
慕雪6442864

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){

        

    })

}


查看完整回答
反對 回復 2022-09-05
?
呼啦一陣風

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)


查看完整回答
反對 回復 2022-09-05
  • 3 回答
  • 0 關注
  • 137 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號