Golang 的各种组件很灵便也很弱小,但对于高级入门的使用者来说,要用好着实不易。最近,在开发一个能够拿来即用的 golang 库。第一个组件抉择了缓存,次要是因为这个组件十分的要害,但也十分不容易实现好。

第一步:定义 Cache 接口

设计一个高扩大的缓存包,就须要利用 里氏替换准则(Liskov Substitution Principle),做好形象,将缓存定义为接口

type Cache interface {    ...}

第二步:组织包构造

而后,实现一个具体的 LRU 缓存,那么此时首先要组织好包构造,如下:

|-cache| |-lru| | |-lru.go| | |-segment.go| | |-options.go| | |-expvar.go|-cache.go

利用包划分档次,将接口放在根包下,作为所有子包的通用语言:

// cache.gopackage edgetype Cache interface {    ...}

第三步:实现 LRU 缓存

  1. 为了避免锁竞争导致的性能低下,此处应用分段加锁的形式升高锁粒度以进步缓存性能
  2. 同时将 segmentnewSegmentcache 以小写命名,防止对外裸露实现细节
  3. 应用 Higher-order function,实现可扩大的配置参数
  4. 应用 expvar 裸露缓存的状态
// lru.gopackage lrutype cache struct {    ...}func New(opts ...Opt) (*cache, error) {    ...}// segment.gopackage lrutype segment struct {    ...}func newSegment(c int) *segment {    ...}// options.gotype options struct {    ...}type Opt func(*options)func WithConcurrency(c int) Opt {    return func(o *options) {        o.concurrency = c    }}func WithCapacity(c int) Opt {    return func(o *options) {        o.capacity = c    }}// expvar.govar m = struct {    Get    *expvar.Int    Set    *expvar.Int    Delete *expvar.Int    Exists *expvar.Int    Hit    *expvar.Int    Evict  *expvar.Int}{    Get:    expvar.NewInt("cache.lru.get"),    Set:    expvar.NewInt("cache.lru.set"),    Delete: expvar.NewInt("cache.lru.delete"),    Exists: expvar.NewInt("cache.lru.exists"),    Hit:    expvar.NewInt("cache.lru.hit"),    Evict:  expvar.NewInt("cache.lru.evict"),}

第四步:完结了么?

当然没有,从以上能够看到,以下几点:

  1. options 能够做到多种实现共用,更应该放在 cache 文件夹下。
  2. 在应用时,lru.New() 赋值给 Cache 接口稍微不天然
  3. segment.go 和 expvar.go 未对使用者凋谢但文件却对外裸露
  4. segment 可能后续会用来实现其余缓存算法,也不适宜放在 lru 包下

基于以上起因,再次调整包构造如下:

|-cache| |-options.go| |-lru.go|-cache.go|-internal| |-cache| | |-lru| | | |-expvar.go| | | |-segment.go

同时,调整 LRU 缓存的接口为:

// cache.gopackage cachetype cache struct {    ...}func NewLRU(opts ...Opt) (*cache, error) {    ...}

是不是天然了很多,应用示例:

var c edge.Cache = cache.NewLRU()

总结

学以致用,此 LRU 的实现利用了很多之前的常识。谋求优良代码的路是没有止境的,下课。

源代码:github.com/cyningsun/edge

本文作者:cyningsun
本文地址: https://www.cyningsun.com/07-...
版权申明:本博客所有文章除特地申明外,均采纳 CC BY-NC-ND 3.0 CN 许可协定。转载请注明出处!