9.go开源groupcache项目笔记——lru代码

来源:互联网 发布:认知语言学与人工智能 编辑:程序博客网 时间:2024/06/06 23:06

9.go开源groupcache项目笔记——lru代码

LRU是LeastRecently Used 近期最少使用算法。

内存管理的一种页面置换算法,对于在内存中但又不用的数据块(内存块)叫做LRU,操作系统会根据哪些数据属于LRU而将其移出内存而腾出空间来加载另外的数据。

       LRU用于实现LRU 的cache.

1      LRU文件

1.1     Cache结构体

先定义了一个cache结构体。

MaxEntries int是最大CACHE容量。

OnEvicted func(key Key, value interface{}) 是一个可选的回调函数,当一个ITEM从CACHE中清除的时候调用。

ll   *list.List是一个链表的指针

cache map[interface{}]*list.Element 是一个map类型,为列表中元素的指针。

PS:interface{},在Go中它可以指向任意对象,也就任意对象都是先这个接口,你可以把它看成Java/C#中的Object, C/C++中的void*。list.Element其指向的类型是entry类型

1.2     其他定义

定义Key为接口,表示Key可以为任何值。

定义entry为结构体,包含key和value。其中key为Key类型,value为接口。

2      New函数

返回一个Cache结构体。

入参为一个整数,就是CACHE支持的最大容量,如果为0表示无上线

创建一个新的链表。

3      Add函数

入参为key Key,value interface{}.

首先判断当前Cache是否为nil,如果为nil则先new一个出来。

如果已经存在该key则将该元素指针移到列表前面,并将对应的值进行更新,代码如:ee.Value.(*entry).value= value 然后。

如果该key不存在,则将新的值添加到列表最前面,同时加入到Cache结构体中cache,接着判断是否超过了CACHE的最大数量,超过则调用RemoveOldest来删除最旧的entry。

4      Get函数

入参为key类型为Key。返回value和是否ok.

如果不存在缓存则直接换回。

如果存在就意味着命中,将元素指针移到列表前面,然后返回元素和TRUE

5      Remove函数

如果缓存不存在,则直接返回。

如果存在,调用removeElement移除指针。

6      RemoveOldest函数

如果缓存不存在,则直接返回。

如果有缓存则调用removeElement从列表的后端开始删除。

7      removeElement函数

入参为列表指针。

直接调用列表的Remove函数删除指针。

然后使用delete命令从map(c.cache)中删除对应的项

如果有回调函数则调用回调函数。

8      Len函数

返回列表长度,如果Cache结构体中的map为nil直接返回0.

PS:Go中实现一个类的成员方法,在func之后加类,在Go中接口的实现并不是和Java中那样子,而是只要某个类只要实现了某个接口的所有方法,即可认为该类实现了该接口。

Go中开头字母大写的变量名,类名,方法名表示对外可知,小写开头的表示对外不暴露。另外类实这种代码ele.Value.(*entry).value,其中(*entry)表示将Value转成*entry类型访问。

9      LRU_TESET

用于测试lru。

定义了两个结构体simpleStructcomplexStruct

然后定义一个变量getTests,如下

vargetTests=[]struct{

    name       string

    keyToAdd   interface{}

    keyToGet   interface{}

    expectedOkbool

}{

    {"string_hit","myKey","myKey",true},

    {"string_miss","myKey","nonsense",false},

    {"simple_struct_hit",simpleStruct{1,"two"},simpleStruct{1,"two"},true},

    {"simeple_struct_miss",simpleStruct{1,"two"},simpleStruct{0,"noway"},false},

    {"complex_struct_hit",complexStruct{1,simpleStruct{2,"three"}},

        complexStruct{1,simpleStruct{2,"three"}},true},

}

主要是两个用例如下

9.1     TestGet

从变量getTests循环获取,先调用New创建一个lru.

然后根据getTests. keyToAdd来增加缓存。每个键值都为1234.

然后在增加完后进行获取键值是否满足条件。

循环结束后测试也结束。

9.2     TestRemove

先增加一个lru。

然后增加一个键值,测试OK

然后将键值删除。检查删除是否成功。

9.3     测试结果

=== RUN TestGet

--- PASS: TestGet (0.00s)

=== RUN TestRemove

--- PASS: TestRemove(0.00s)

PASS

ok test 0.135s

 

 

 

 

原创粉丝点击