github.com/aaabigfish/gopkg@v1.1.0/cache/lrucache/lrucache.go (about) 1 package lrucache 2 3 // Element - node to store cache item 4 type Element struct { 5 prev, next *Element 6 Key interface{} 7 Value interface{} 8 } 9 10 // Next - fetch older element 11 func (e *Element) Next() *Element { 12 return e.next 13 } 14 15 // Prev - fetch newer element 16 func (e *Element) Prev() *Element { 17 return e.prev 18 } 19 20 // LRUCache - a data structure that is efficient to insert/fetch/delete cache items [both O(1) time complexity] 21 type LRUCache struct { 22 cache map[interface{}]*Element 23 head *Element 24 tail *Element 25 capacity int 26 } 27 28 // New - create a new lru cache object 29 func New(capacity int) *LRUCache { 30 return &LRUCache{make(map[interface{}]*Element), nil, nil, capacity} 31 } 32 33 // Put - put a cache item into lru cache 34 func (lc *LRUCache) Put(key interface{}, value interface{}) { 35 if e, ok := lc.cache[key]; ok { 36 e.Value = value 37 lc.refresh(e) 38 return 39 } 40 41 if lc.capacity == 0 { 42 return 43 } else if len(lc.cache) >= lc.capacity { 44 // evict the oldest item 45 delete(lc.cache, lc.tail.Key) 46 lc.remove(lc.tail) 47 } 48 49 e := &Element{nil, lc.head, key, value} 50 lc.cache[key] = e 51 if len(lc.cache) != 1 { 52 lc.head.prev = e 53 } else { 54 lc.tail = e 55 } 56 lc.head = e 57 } 58 59 // Get - get value of key from lru cache with result 60 func (lc *LRUCache) Get(key interface{}) (interface{}, bool) { 61 if e, ok := lc.cache[key]; ok { 62 lc.refresh(e) 63 return e.Value, ok 64 } 65 return nil, false 66 } 67 68 // Delete - delete item by key from lru cache 69 func (lc *LRUCache) Delete(key interface{}) { 70 if e, ok := lc.cache[key]; ok { 71 delete(lc.cache, key) 72 lc.remove(e) 73 } 74 } 75 76 // Range - calls f sequentially for each key and value present in the lru cache 77 func (lc *LRUCache) Range(f func(key, value interface{}) bool) { 78 for i := lc.head; i != nil; i = i.Next() { 79 if !f(i.Key, i.Value) { 80 break 81 } 82 } 83 } 84 85 // Update - inplace update 86 func (lc *LRUCache) Update(key interface{}, f func(value *interface{})) { 87 if e, ok := lc.cache[key]; ok { 88 f(&e.Value) 89 lc.refresh(e) 90 } 91 } 92 93 // Front - get front element of lru cache 94 func (lc *LRUCache) Front() *Element { 95 return lc.head 96 } 97 98 // Back - get back element of lru cache 99 func (lc *LRUCache) Back() *Element { 100 return lc.tail 101 } 102 103 // Len - length of lru cache 104 func (lc *LRUCache) Len() int { 105 return len(lc.cache) 106 } 107 108 // Capacity - capacity of lru cache 109 func (lc *LRUCache) Capacity() int { 110 return lc.capacity 111 } 112 113 func (lc *LRUCache) refresh(e *Element) { 114 if e.prev != nil { 115 e.prev.next = e.next 116 if e.next == nil { 117 lc.tail = e.prev 118 } else { 119 e.next.prev = e.prev 120 } 121 e.prev = nil 122 e.next = lc.head 123 lc.head.prev = e 124 lc.head = e 125 } 126 } 127 128 func (lc *LRUCache) remove(e *Element) { 129 if e.prev == nil { 130 lc.head = e.next 131 } else { 132 e.prev.next = e.next 133 } 134 if e.next == nil { 135 lc.tail = e.prev 136 } else { 137 e.next.prev = e.prev 138 } 139 }