实现一个带超时检测和容量限制的LRU缓存,面试的时候脑子浆糊没有写出来
package main
import (
"container/list"
"fmt"
"sync"
"time"
)
type Entry struct {
Key, Val int
Time time.Time
}
type Cache struct {
sync.Mutex
mp map[int]*list.Element
ll list.List
size_limit int
closed bool
}
func (c *Cache) Get(key int) (int, bool) {
c.Lock()
defer c.Unlock()
if elem, ok := c.mp[key]; ok {
c.ll.MoveToFront(elem)
value := elem.Value.(Entry).Val
elem.Value = Entry{Key: key, Val: value, Time: time.Now()}
return value, true
}
return 0, false
}
func (c *Cache) Set(key, val int) bool {
c.Lock()
defer c.Unlock()
if elem, ok := c.mp[key]; ok {
// key already exists, refresh the key
elem.Value = Entry{Key: key, Val: val, Time: time.Now()}
c.ll.MoveToFront(elem)
return true
}
// create a new element
elem := c.ll.PushFront(Entry{Key: key, Val: val, Time: time.Now()})
c.mp[key] = elem
for len(c.mp) > c.size_limit {
deleted_elem := c.ll.Back()
deleted_key, deleted_value := (deleted_elem.Value).(Entry).Key, (deleted_elem.Value).(Entry).Val
c.ll.Remove(deleted_elem)
delete(c.mp, deleted_key)
fmt.Printf("##### K-V pair (%d : %d) is removed due to limited capacity\n", deleted_key, deleted_value)
}
return true
}
func (c *Cache) Eliminate(life_span int) {
for {
if c.closed {
fmt.Printf("Eliminator goroutine exits\n")
break
}
c.Lock()
// check the time of all K-V pairs
for key, elem := range c.mp {
if elem.Value.(Entry).Time.Add(10 * time.Second).Before(time.Now()) {
// eliminate the K-V pair
c.ll.Remove(elem)
delete(c.mp, key)
fmt.Printf("##### K-V pair (%d : %d) is expired\n", key, elem.Value.(Entry).Val)
}
}
c.Unlock()
}
}
func main() {
cache := Cache{
mp: make(map[int]*list.Element),
ll: list.List{},
size_limit: 3,
Mutex: sync.Mutex{},
closed: false,
}
go cache.Eliminate(10)
var operation string
var key, value int
for {
fmt.Scan(&operation)
if operation == `set` {
fmt.Scan(&key, &value)
cache.Set(key, value)
fmt.Printf("K-V pair (%d : %d) is set\n", key, value)
} else if operation == `get` {
fmt.Scan(&key)
v, ok := cache.Get(key)
if ok {
fmt.Printf("Value for key = %d is %d\n", key, v)
} else {
fmt.Printf("Key = %d doesn't exist\n", key)
}
} else if operation == `over` {
cache.closed = true
break
} else {
fmt.Printf("invalid operation\n")
}
}
}