极客兔兔Gee-Cache Day2

时间:2024-10-05 18:23:22
// --------------------------------------------------------------------------------------- // ByteView.go 缓存元素的抽象 package gee // 只读数据结构 表示缓存值,实现了Value接口 type ByteView struct { b []byte } func (v ByteView) Len() int { return len(v.b) } func (v ByteView) ByteSlice() []byte { return cloneBytes(v.b) } func cloneBytes(b []byte) []byte { c := make([]byte, len(b)) copy(c, b) return c } func (v ByteView) String() string { return string(v.b) } // cache.go 对day1中的lru加上并发控制 package gee // --------------------------------------------------------------------------------------- // 实现并发控制 import ( "sync" ) type cache struct { mu sync.Mutex lru *Cache cacheBytes int64 } func (c *cache) add(key string, value ByteView) { c.mu.Lock() defer c.mu.Unlock() if c.lru == nil { // 延迟初始化 c.lru = New(c.cacheBytes, nil) } c.lru.Add(key, value) } func (c *cache) get(key string) (value ByteView, ok bool) { c.mu.Lock() defer c.mu.Unlock() if c.lru == nil { return } if v, ok := c.lru.Get(key); ok { return v.(ByteView), ok } return } // --------------------------------------------------------------------------------------- // geecache.go 与源数据库进行交互 package gee // 实现与外部交互 import ( "fmt" "sync" ) type Getter interface { Get(key string) ([]byte, error) } type GetterFunc func(key string) ([]byte, error) // 接口型函数 func (f GetterFunc) Get(key string) ([]byte, error) { return f(key) } type Group struct { name string // 缓存名称 getter Getter // 回调函数 mainCache cache // 缓存 } var ( mu sync.Mutex groups = make(map[string]*Group) ) func NewGroup(name string, cacheBytes int64, getter Getter) *Group { if getter == nil { panic("Getter nil") } mu.Lock() defer mu.Unlock() g := &Group{ name: name, getter: getter, mainCache: cache{cacheBytes: cacheBytes}, } groups[name] = g return g } func GetGroup(name string) *Group { mu.Lock() defer mu.Unlock() g := groups[name] return g } func (g *Group) Get(key string) (ByteView, error) { if key == "" { return ByteView{}, fmt.Errorf("key is nil") } if v, ok := g.mainCache.get(key); ok { fmt.Println("Gee Cache hit") return v, nil } return g.load(key) } func (g *Group) load(key string) (Value ByteView, err error) { return g.getLocally(key) } // 调用回调函数,去源数据库查找内容 func (g *Group) getLocally(key string) (ByteView, error) { bytes, err := g.getter.Get(key) if err != nil { return ByteView{}, err } value := ByteView{b: cloneBytes(bytes)} g.add(key, value) return value, nil } func (g *Group) add(key string, value ByteView) { g.mainCache.add(key, value) }