go实现LRU
package lru
import (
"container/list"
)
type Cache struct {
maxBytes int64
nBytes int64
ll *list.List
cache map[string]*list.Element
onEvicted func(key string, value Value)
}
type entry struct {
key string
value Value
}
type Value interface {
Len() int
}
func New(maxBytes int64, onEvicted func(key string, value Value)) *Cache {
cache := &Cache{
maxBytes: maxBytes,
nBytes: 0,
ll: list.New(),
cache: make(map[string]*list.Element),
onEvicted: onEvicted,
}
return cache
}
func (this *Cache) put(key string, value Value) {
ele, ok := this.cache[key]
if ok {
this.ll.MoveToFront(ele)
element := ele.Value.(*entry)
this.nBytes += int64(value.Len()) - int64(element.value.Len())
element.value = value
} else {
element := this.ll.PushFront(&entry{key, value})
this.cache[key] = element
this.nBytes += int64(len(key)) + int64(value.Len())
}
if this.maxBytes != 0 && this.maxBytes < this.nBytes {
this.removeOldest()
}
}
func (this *Cache) removeOldest() {
ele := this.ll.Back()
if ele != nil {
this.ll.Remove(ele)
element := ele.Value.(*entry)
delete(this.cache, element.key)
this.nBytes -= int64(len(element.key)) + int64(element.value.Len())
if this.onEvicted != nil {
this.onEvicted(element.key, element.value)
}
}
}
func (this *Cache) Get(key string) (value Value, ok bool) {
element := this.cache[key]
if element != nil {
this.ll.MoveToFront(element)
kv := element.Value.(*entry)
return kv.value, true
} else {
return nil, false
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
编辑 (opens new window)
上次更新: 2024/02/22, 14:03:19