原文地址:Golang实现LRU算法~
LRU是Least Recently Used的缩写,即最近最少使用,是一种常用的缓存淘汰算法,选择最近最久未使用的数据予以淘汰,该算法赋予每个数据一个访问字段,用来记录一个元素自上次被访问以来所经历的时间 t,当须淘汰一个数据时,选择现有数据中其 t 值最大的,即最近最少使用的页面予以淘汰。
Go可用链表数据结构来省去设置访问时间t字段,可将经常访问的数据插入链表头,而链表尾部的数据自然就成为最久未访问的数据。
代码实现如下:
package mainimport ( "container/list" "errors" "sync")type Lru struct { max int l *list.List Call func(key interface{}, value interface{}) cache map[interface{}]*list.Element mu *sync.Mutex}type Node struct { Key interface{} Val interface{}}func NewLru(len int) *Lru { return &Lru{ max: len, l: list.New(), cache: make(map[interface{}]*list.Element), mu: new(sync.Mutex), }}func (l *Lru) Add(key interface{}, val interface{}) error { if l.l == nil { return errors.New("not init NewLru") } l.mu.Lock() defer l.mu.Unlock() if e, ok := l.cache[key]; ok { e.Value.(*Node).Val = val l.l.MoveToFront(e) return nil } ele := l.l.PushFront(&Node{ Key: key, Val: val, }) l.cache[key] = ele if l.max != 0 && l.l.Len() > l.max { if e := l.l.Back(); e != nil { l.l.Remove(e) node := e.Value.(*Node) delete(l.cache, node.Key) if l.Call != nil { l.Call(node.Key, node.Val) } } } return nil}func (l *Lru) Get(key interface{}) (val interface{}, ok bool) { if l.cache == nil { return } l.mu.Lock() defer l.mu.Unlock() if ele, ok := l.cache[key]; ok { l.l.MoveToFront(ele) return ele.Value.(*Node).Val, true } return}func (l *Lru) GetAll() []*Node { l.mu.Lock() defer l.mu.Unlock() var data []*Node for _, v := range l.cache { data = append(data, v.Value.(*Node)) } return data}func (l *Lru) Del(key interface{}) { if l.cache == nil { return } l.mu.Lock() defer l.mu.Unlock() if ele, ok := l.cache[key]; ok { delete(l.cache, ele) if e := l.l.Back(); e != nil { l.l.Remove(e) delete(l.cache, key) if l.Call != nil { node := e.Value.(*Node) l.Call(node.Key, node.Val) } } }}
上述代码的LRU算法实现比较简单,主要是选择已有的双向链表数据结构,其包含很多方便的方法供使用,由此可以看出在日常开发中,选择合适的数据结构来实现特定的功能是非常重要的,能达到事半功倍的效果,当然还有其他的方法来实现LRU算法,这里就不一一例举了。
至此,本次分享就结束了,后期会慢慢补充。
以上仅为个人观点,不一定准确,能帮到各位那是最好的。
好啦,到这里本文就结束了,喜欢的话就来个三连击吧。
扫码关注公众号,获取更多优质内容。



