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();
}

  

使用go语言的list实现一个简单的LRU缓存的更多相关文章

  1. C语言中如何写一个简单可移植而又足够随机的随机数生成器

    在C语言中标准库中的随机数产生函数的返回可能不是最优的,因为有些随机数生成器的低位并不随机,而另一些返回随机数的函数实现上又太复杂鸟.所以rand()%N并不是一个好方法,牛人给出的建议是使用: ra ...

  2. 一个简单的带缓存http代理

    眼下1.0版模型非常easy.即对客户机发来的请求进行简单处理后,转发到server.转发之前先检查本地缓存.假设有.则直接回送给客户本地资源 程序流程大致例如以下图: 缓存是通过把文件保存到磁盘上, ...

  3. 搭建一个简单的dns缓存服务器

    环境:linux 软件:bind97,bind97-utils, bind97-libs ip:192.168.192.130:192.168.192.131 -------------------- ...

  4. C#简单实现LRU缓存

    最近跟同学吃饭扯淡的时候,由技术扯到薪资,又由薪资扯到他找工作时跟面试官是怎么扯淡拿高工资的,各种技术一顿侃,总之只要啥都了解就没问题了.谈到缓存的时候,我试探性的问了问- -你还记得LRU怎么写吗, ...

  5. Golang校招简历项目-简单的分布式缓存

    前言 前段时间,校招投了golang岗位,但是没什么好的项目往简历上写,于是参考了许多网上资料,做了一个简单的分布式缓存项目. 现在闲下来了,打算整理下. github项目地址:https://git ...

  6. 为什么C语言在2013年仍然很重要:一个简单的例子

    附注:在最初的文章里,我没说明进行模2^64的计算——我当然明白那些不是“正确的”斐波那契数列,其实我不是想分析大数,我只是想探寻编译器产生的代码和计算机体系结构而已. 最近,我一直在开发Dynvm— ...

  7. 一个简单的C语言程序(详解)

    C Primer Plus之一个简单的C语言程序(详解) #include <stdio.h> int main(void) //一个简单的 C程序 { int num; //定义一个名为 ...

  8. 用C语言编写一个简单的词法分析程序

    问题描述: 用C或C++语言编写一个简单的词法分析程序,扫描C语言小子集的源程序,根据给定的词法规则,识别单词,填写相应的表.如果产生词法错误,则显示错误信息.位置,并试图从错误中恢复.简单的恢复方法 ...

  9. 用Go语言实现一个简单的聊天机器人

    一.介绍 目的:使用Go语言写一个简单的聊天机器人,复习整合Go语言的语法和基础知识. 软件环境:Go1.9,Goland 2018.1.5. 二.回顾 Go语言基本构成要素:标识符.关键字.字面量. ...

随机推荐

  1. UML类图实例分析

    登录模块 某基于C/S的即时聊天系统登录模块功能描述如下: 用户通过登录界面(LoginForm)输入账号和密码,系统将输入的账号和密码与存储在数据库(User)表中的用户信息进行比较,验证用户输入是 ...

  2. Spring事务异常rollback-only

    转自:https://blog.csdn.net/sgls652709/article/details/49472719 前言 在利用单元测试验证spring事务传播机制的时候出现了下面的异常: Tr ...

  3. week05 06绑定滚动条 去抖动

    像这种小代码 为了满足某种需求 可以直接上网搜 这些都是JS代码和react无关 我们下拉 就会触发事件从而调用loading more news 那个函数 react要求我们加个key key就是唯 ...

  4. 使用firefox插件httperrequest,模拟发送及接收Json请求 【转】

    转自[http://blog.csdn.net/feixue1232/article/details/8535212] 目标:使用httpreques\Json-Handle\tcpdump\wire ...

  5. yum源制作

    CentOS7 同步远程镜像 搭建本地yum服务器同步CentOS镜像站点的数据到本地服务器,使用nginx实现http服务向局域网内的其他机器提供yum服务,解决内网yum安装软件的问题. 一.前提 ...

  6. yii添加模型基础类

  7. 《深入理解JAVA虚拟机》----------第三章 垃圾收集器与内存分配策略,笔记(下)

    1.垃圾收集器 1.1 Serial收集器 这个收集器是一个单线程的收集器,它在进行垃圾收集时,必须暂停其他所有的工作线程. 它是虚拟机运行在Client模式下的默认新生代收集器,它简单而高效. 1. ...

  8. python遇到的错误

    今天学习文件遇到这个错误. 这是在 text_files\vvvv.txt  之间加一个\ 就可以了,变成  text_files\\vvvv.txt,运行成功

  9. flume 实际的使用

    1.No configuration found for this host:seqGenSrc bin/flume-ng agent --conf conf --conf-file conf/flu ...

  10. java.lang.NoClassDefFoundError: net.tsz.afinal.FinalHttp

    java.lang.NoClassDefFoundError: net.tsz.afinal.FinalHttpat com.hbjyjt.oa.utils.i.<init>(HttpRe ...