package main; import ( "container/list" "errors" "sync" "fmt" "encoding/json" ) //LRU(Least recently used)最近最少使用,算法根據數據的歷史訪問記錄來進行淘汰數據 //核心思想是"如果數據最近被訪問過,那么將來被訪問的幾率也更高" //常見的實現方式是用一個鏈表保存數據 //1. 新數據插入到鏈表頭部 //2. 每當緩存命中(即緩存數據被訪問),則將數據移到鏈表頭部 //3. 當鏈表滿的時候,將鏈表尾部的數據丟棄 type cacheItem struct { Key string; Val interface{}; } type LRU struct { //最大存儲數量 maxNum int; //當前存儲數量 curNum int; //鎖,保證數據一致性 mutex sync.Mutex; //鏈表 data *list.List; } //添加數據 func (l *LRU) add(key string, value interface{}) error { //判斷key是否存在 if e, _ := l.exist(key); e { return errors.New(key + "已存在"); } //判斷當前存儲數量與最大存儲數量 if l.maxNum == l.curNum { //鏈表已滿,則刪除鏈表尾部元素 l.clear(); } l.mutex.Lock(); l.curNum++; //json序列化數據 data, _ := json.Marshal(cacheItem{key, value}); //把數據保存到鏈表頭部 l.data.PushFront(data); l.mutex.Unlock(); return nil; } //設置數據 func (l *LRU) set(key string, value interface{}) error { e, item := l.exist(key); if !e { return l.add(key, value); } l.mutex.Lock(); data, _ := json.Marshal(cacheItem{key, value}); //設置鏈表元素數據 item.Value = data; l.mutex.Unlock(); return nil; } //清理數據 func (l *LRU) clear() interface{} { l.mutex.Lock(); l.curNum--; //刪除鏈表尾部元素 v := l.data.Remove(l.data.Back()); l.mutex.Unlock(); return v; } //獲取數據 func (l *LRU) get(key string) interface{} { e, item := l.exist(key); if !e { return nil; } l.mutex.Lock(); //數據被訪問,則把元素移動到鏈表頭部 l.data.MoveToFront(item); l.mutex.Unlock(); var data cacheItem; json.Unmarshal(item.Value.([]byte), &data); return data.Val; } //刪除數據 func (l *LRU) del(key string) error { e, item := l.exist(key); if !e { return errors.New(key + "不存在"); } l.mutex.Lock(); l.curNum--; //刪除鏈表元素 l.data.Remove(item); l.mutex.Unlock(); return nil; } //判斷是否存在 func (l *LRU) exist(key string) (bool, *list.Element) { var data cacheItem; //循環鏈表,判斷key是否存在 for v := l.data.Front(); v != nil; v = v.Next() { json.Unmarshal(v.Value.([]byte), &data); if key == data.Key { return true, v; } } return false, nil; } //返回長度 func (l *LRU) len() int { return l.curNum; } //打印鏈表 func (l *LRU) print() { var data cacheItem; for v := l.data.Front(); v != nil; v = v.Next() { json.Unmarshal(v.Value.([]byte), &data); fmt.Println("key:", data.Key, " value:", data.Val); } } //創建一個新的LRU func LRUNew(maxNum int) *LRU { return &LRU{ maxNum: maxNum, curNum: 0, mutex: sync.Mutex{}, data: list.New(), }; } func main() { lru := LRUNew(5); lru.add("1111", 1111); lru.add("2222", 2222); lru.add("3333", 3333); lru.add("4444", 4444); lru.add("5555", 5555); lru.print(); //get成功后,可以看到3333元素移動到了鏈表頭 fmt.Println(lru.get("3333")); lru.print(); //再次添加元素,如果超過最大數量,則刪除鏈表尾部元素,將新元素添加到鏈表頭 lru.add("6666", 6666); lru.print(); lru.del("4444"); lru.print(); lru.set("2222", "242424"); lru.print(); }