go开源gro pcache项目笔记-lr 代码
lru是leastrecently used 近期最少使用算法。 内存管理的一种页面置换算法,对于在内存中但又不用的数据块(内存块)叫做lru,操作系统会根据哪些数据属于lru而将其移出内存而腾出空间来加载另外的数据。 lru用于实现lru 的cache. 1 lru文件 1.1 cache结构体 先定义了一个cache结构体。 maxentries int是最大cache容量。 onevicted f nc(key key, val e interface{}) 是一个可选的回调函数,当一个item从cache中清除的时候调用。 ll *list.list是一个链表的指针 cache map[interface{}]*list.element 是一个map类型,为列表中元素的指针。 ps:interface{},在go中它可以指向任意对象,也就任意对象都是先这个接口,你可以把它看成javac#中的object, cc中的void*。list.element其指向的类型是entry类型 1.2 其他定义 定义key为接口,表示key可以为任何值。 定义entry为结构体,包含key和val e。其中key为key类型,val e为接口。 2 new函数 返回一个cache结构体。 入参为一个整数,就是cache支持的最大容量,如果为0表示无上线 创建一个新的链表。 3 add函数 入参为key key,val e interface{}. 首先判断当前cache是否为nil,如果为nil则先new一个出来。 如果已经存在该key则将该元素指针移到列表前面,并将对应的值进行更新,代码如:ee.val e.(*entry).val e= val e 然后。 如果该key不存在,则将新的值添加到列表最前面,同时加入到cache结构体中cache,接着判断是否超过了cache的最大数量,超过则调用removeoldest来删除最旧的entry。 4 get函数 入参为key类型为key。返回val e和是否ok. 如果不存在缓存则直接换回。 如果存在就意味着命中,将元素指针移到列表前面,然后返回元素和true 5 remove函数 如果缓存不存在,则直接返回。 如果存在,调用removeelement移除指针。 6 removeoldest函数 如果缓存不存在,则直接返回。 如果有缓存则调用removeelement从列表的后端开始删除。 7 removeelement函数 入参为列表指针。 直接调用列表的remove函数删除指针。 然后使用delete命令从map(c.cache)中删除对应的项 如果有回调函数则调用回调函数。 8 len函数 返回列表长度,如果cache结构体中的map为nil直接返回0. ps:go中实现一个类的成员方法,在f nc之后加类,在go中接口的实现并不是和java中那样子,而是只要某个类只要实现了某个接口的所有方法,即可认为该类实现了该接口。 go中开头字母大写的变量名,类名,方法名表示对外可知,小写开头的表示对外不暴露。另外类实这种代码ele.val e.(*entry).val e,其中(*entry)表示将val e转成*entry类型访问。 9 lru_teset 用于测试lr 。 定义了两个结构体simplestr ct,complexstr ct 然后定义一个变量gettests,如下 var gettests=[] str ct { name string keytoadd interface {} keytoget interface {} expectedokbool }{ {"string_hit","mykey","mykey",tr e}, {"string_miss","mykey","nonsense",false}, {"simple_str ct_hit",simplestr ct{1,"two"},simplestr ct{1,"two"},tr e}, {"simeple_str ct_miss",simplestr ct{1,"two"},simplestr ct{0,"noway"},false}, {"complex_str ct_hit",complexstr ct{1,simplestr ct{2,"three"}}, complexstr ct{1,simplestr ct{2,"three"}},tr e}, } 主要是两个用例如下 9.1 testget 从变量gettests循环获取,先调用new创建一个lr . 然后根据gettests. keytoadd来增加缓存。每个键值都为1234. 然后在增加完后进行获取键值是否满足条件。 循环结束后测试也结束。 9.2 testremove 先增加一个lr 。 然后增加一个键值,测试ok 然后将键值删除。检查删除是否成功。