欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 旅游 > 极客兔兔Gee-Cache Day2

极客兔兔Gee-Cache Day2

2025/9/11 6:51:58 来源:https://blog.csdn.net/qq_40052678/article/details/142708296  浏览:    关键词:极客兔兔Gee-Cache Day2
  • 接口型函数

    • // 定义接口
      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)
      }
      
    • 价值:能将普通的函数类型作为参数,也能将结构体作为参数,使用更为灵活

    • 例如:

      • // 若GetFromSource定义如下,需要传一个Getter作为参数
        func GetFromSource(getter Getter, key string) []byte
        // 1.传函数(匿名函数和非匿名函数,下面是匿名)
        // 将函数类型转换为GetterFunc,这是实现了Getter接口的,可以传
        GetFromSource(GetterFunc(func(key string) ([]byte, error) {return []byte(key), nil
        }), "hello")
        // 2.传结构体
        type DB struct{ url string}
        func (db *DB) Get(key string) ([]byte, error) {// ...return []byte(v), nil
        }
        func main() {GetFromSource(new(DB), "hello")
        }
        
    • net/http包下的Handler就是使用这种特性

      • type Handler interface {ServeHTTP(ResponseWriter, *Request)
        }
        type HandlerFunc func(ResponseWriter, *Request)func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {f(w, r)
        }
        
  • sync.Mutex:Go 语言标准库提供的一个互斥锁,当一个协程(goroutine)获得了这个锁的拥有权后,其它请求锁的协程(goroutine) 就会阻塞在 Lock() 方法的调用上,直到调用 Unlock() 锁被释放。

  • reflect.DeepEqual()

    • 对于基本数据类型(整数、布尔、字符串),与==相同
    • 可以比较数组、切片、结构体、map、接口等是否相同
    • 对于切片,必须切片长度相等且顺序相同,元素相同
  • day2由四个文件组成,分别是lru.gobyteview.gocache.gogeecache.go

    • lru.golru缓存淘汰策略

    • byteview.go:缓存值,实现了Value接口

    • cache.go:并发控制

    • geecache.go:与外部交互,在缓存未命中时去查找数据源

    • cache.goday1中的lru加入了锁机制,实现并发下的互斥访问,geecache.go中实现了Group结构体,其中包含cache和回调函数,在cache未命中时会调用回调函数查找数据库中的内容,同时,使用map结构分配多个缓存,用name进行区分,每个Group有一个唯一的name(例如学生成绩和学生课程的缓存使用不同的name区分)

    • 代码

      // ---------------------------------------------------------------------------------------
      // 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.Mutexlru        *CachecacheBytes 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.Mutexgroups = 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] = greturn 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)
      }

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词