go-cache学习与源码分析
2021/4/15 22:26:30
本文主要是介绍go-cache学习与源码分析,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
github.com/patrickmn/go-cache go-cache是一款类似于memached 的key/value 缓存软件。它比较适用于单机执行的应用程序。go-cache实质上就是拥有过期时间并且线程安全的map,可以被多个goroutine安全访问。并别代码量也相对较少,今天我们一起对go-cache代码包进行学习。
我们这里先上用法说明
package main import ( "log" "time" "github.com/patrickmn/go-cache" ) func main(){ c := cache.New(30*time.Second, 10*time.Second)//new 一个cache,并且设置默认过期时间30s和清理周期10s。 value, found := c.Get("test") //从cache中读取key 为test的value。 if found { log.Println("found:", value) } else { log.Println("not found") } c.Set("test", "test value", cache.DefaultExpiration) //向cache中写入key/value数据,并且设置过期时间为默认,这里的默认就是我们在new cache时设置怼默认过期时间(30s) value, found := c.Get("test")//从cache中读取key 为test的value。显然我们在这里就能读取到数据了 if found { log.Println("found:", value) } else { log.Println("not found") } time.Sleep(60*time.Second) //我们等待过期时间以后,并且达到清理周期时间 log.Println("sleep 60s...") value, found = c.Get("test")//再次读取key is test的数据,显然此时我们读取不到 if found { log.Println("found:", value) } else { log.Println("not found") } }
看完了用例说明我们再看下具体是怎么实现的;
package cache import ( "encoding/gob" "fmt" "io" "os" "runtime" "sync" "time" ) type Item struct { Object interface{} Expiration int64 } // Returns true if the item has expired. func (item Item) Expired() bool { if item.Expiration == 0 { return false } return time.Now().UnixNano() > item.Expiration } const ( // For use with functions that take an expiration time. NoExpiration time.Duration = -1 // For use with functions that take an expiration time. Equivalent to // passing in the same expiration duration as was given to New() or // NewFrom() when the cache was created (e.g. 5 minutes.) DefaultExpiration time.Duration = 0 ) type Cache struct { *cache // If this is confusing, see the comment at the bottom of New() } type cache struct { defaultExpiration time.Duration items map[string]Item mu sync.RWMutex onEvicted func(string, interface{}) janitor *janitor } // func (c *cache) Set(k string, x interface{}, d time.Duration) { // "Inlining" of set var e int64 if d == DefaultExpiration { d = c.defaultExpiration } if d > 0 { e = time.Now().Add(d).UnixNano() } c.mu.Lock() c.items[k] = Item{ Object: x, Expiration: e, } // TODO: Calls to mu.Unlock are currently not deferred because defer // adds ~200 ns (as of go1.) c.mu.Unlock() } /* 中间代码 */ //定时清理cache 过期结构 type janitor struct { Interval time.Duration stop chan bool } //设置一个循环时钟,执行定时清理cache 的操作 func (j *janitor) Run(c *cache) { ticker := time.NewTicker(j.Interval) for { select { case <-ticker.C: c.DeleteExpired() case <-j.stop: ticker.Stop() return } } } //向runtime 注册的通知Janitor close func stopJanitor(c *Cache) { c.janitor.stop <- true } func runJanitor(c *cache, ci time.Duration) { j := &janitor{ Interval: ci, stop: make(chan bool), } c.janitor = j go j.Run(c) } func newCache(de time.Duration, m map[string]Item) *cache { if de == 0 { de = -1 } c := &cache{ defaultExpiration: de, items: m, } return c } //具体的cache实现, func newCacheWithJanitor(de time.Duration, ci time.Duration, m map[string]Item) *Cache { c := newCache(de, m) //构建cache C := &Cache{c} if ci > 0 { runJanitor(c, ci) //这里是启动过期清理goroutine runtime.SetFinalizer(C, stopJanitor) //如果cache结束,首先通知Janitor关闭 } return C } //这里就是我们用例中new cache的方法了。 func New(defaultExpiration, cleanupInterval time.Duration) *Cache { items := make(map[string]Item) return newCacheWithJanitor(defaultExpiration, cleanupInterval, items) } //与New 方法功能相同唯一不同的就是由cache creator设置items func NewFrom(defaultExpiration, cleanupInterval time.Duration, items map[string]Item) *Cache { return newCacheWithJanitor(defaultExpiration, cleanupInterval, items) }
看完整体实现,我们发现这是一个项目还是蛮简单的。
这篇关于go-cache学习与源码分析的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-24MongoDB资料:新手入门完全指南
- 2024-12-20go-zero 框架的 RPC 服务 启动start和停止 底层是怎么实现的?-icode9专业技术文章分享
- 2024-12-19Go-Zero 框架的 RPC 服务启动和停止的基本机制和过程是怎么实现的?-icode9专业技术文章分享
- 2024-12-18怎么在golang中使用gRPC测试mock数据?-icode9专业技术文章分享
- 2024-12-15掌握PageRank算法核心!你离Google优化高手只差一步!
- 2024-12-15GORM 中的标签 gorm:"index"是什么?-icode9专业技术文章分享
- 2024-12-11怎么在 Go 语言中获取 Open vSwitch (OVS) 的桥接信息(Bridge)?-icode9专业技术文章分享
- 2024-12-11怎么用Go 语言的库来与 Open vSwitch 进行交互?-icode9专业技术文章分享
- 2024-12-11怎么在 go-zero 项目中发送阿里云短信?-icode9专业技术文章分享
- 2024-12-11怎么使用阿里云 Go SDK (alibaba-cloud-sdk-go) 发送短信?-icode9专业技术文章分享