面试题答案
一键面试设计思路
- 定义缓存策略接口:定义一个统一的缓存策略接口,包含如
Get
、Put
等操作方法,这样不同的缓存策略(LRU、LFU)都可以实现这个接口。 - 配置管理:通过配置文件或命令行参数等方式获取缓存策略的配置信息,例如配置为
lru
或lfu
。 - 工厂模式:使用工厂模式根据配置动态创建对应的缓存策略实例。
- 并发安全:为了保证并发安全,可以使用
sync.RWMutex
对缓存操作进行加锁保护。
核心代码
package main
import (
"fmt"
"sync"
)
// 缓存策略接口
type CacheStrategy interface {
Get(key string) (interface{}, bool)
Put(key string, value interface{})
}
// LRU缓存策略实现
type LRUCache struct {
capacity int
cache map[string]interface{}
keys []string
mutex sync.RWMutex
}
func NewLRUCache(capacity int) *LRUCache {
return &LRUCache{
capacity: capacity,
cache: make(map[string]interface{}),
keys: make([]string, 0),
}
}
func (lru *LRUCache) Get(key string) (interface{}, bool) {
lru.mutex.RLock()
defer lru.mutex.RUnlock()
value, exists := lru.cache[key]
if exists {
// 移动到链表头部(这里简单模拟,实际可使用双向链表优化)
for i, k := range lru.keys {
if k == key {
lru.keys = append(lru.keys[:i], lru.keys[i+1:]...)
lru.keys = append([]string{key}, lru.keys...)
break
}
}
}
return value, exists
}
func (lru *LRUCache) Put(key string, value interface{}) {
lru.mutex.Lock()
defer lru.mutex.Unlock()
if _, exists := lru.cache[key]; exists {
// 移动到链表头部
for i, k := range lru.keys {
if k == key {
lru.keys = append(lru.keys[:i], lru.keys[i+1:]...)
lru.keys = append([]string{key}, lru.keys...)
break
}
}
} else {
if len(lru.keys) >= lru.capacity {
// 删除最久未使用的
delete(lru.cache, lru.keys[len(lru.keys)-1])
lru.keys = lru.keys[:len(lru.keys)-1]
}
lru.keys = append([]string{key}, lru.keys...)
}
lru.cache[key] = value
}
// LFU缓存策略实现
type LFUCache struct {
capacity int
cache map[string]struct {
value interface{}
frequency int
}
frequencyMap map[int][]string
mutex sync.RWMutex
}
func NewLFUCache(capacity int) *LFUCache {
return &LFUCache{
capacity: capacity,
cache: make(map[string]struct {
value interface{}
frequency int
}),
frequencyMap: make(map[int][]string),
}
}
func (lfu *LFUCache) Get(key string) (interface{}, bool) {
lfu.mutex.RLock()
defer lfu.mutex.RUnlock()
item, exists := lfu.cache[key]
if exists {
// 增加频率
lfu.increaseFrequency(key, item.frequency)
return item.value, true
}
return nil, false
}
func (lfu *LFUCache) Put(key string, value interface{}) {
lfu.mutex.Lock()
defer lfu.mutex.Unlock()
if _, exists := lfu.cache[key]; exists {
// 更新值并增加频率
lfu.cache[key].value = value
lfu.increaseFrequency(key, lfu.cache[key].frequency)
} else {
if len(lfu.cache) >= lfu.capacity {
// 删除最不经常使用的
lfu.removeLeastFrequent()
}
lfu.cache[key] = struct {
value interface{}
frequency int
}{value, 1}
lfu.frequencyMap[1] = append(lfu.frequencyMap[1], key)
}
}
func (lfu *LFUCache) increaseFrequency(key string, oldFreq int) {
// 从旧频率列表中移除
for i, k := range lfu.frequencyMap[oldFreq] {
if k == key {
lfu.frequencyMap[oldFreq] = append(lfu.frequencyMap[oldFreq][:i], lfu.frequencyMap[oldFreq][i+1:]...)
break
}
}
newFreq := oldFreq + 1
lfu.cache[key].frequency = newFreq
lfu.frequencyMap[newFreq] = append(lfu.frequencyMap[newFreq], key)
}
func (lfu *LFUCache) removeLeastFrequent() {
for freq := 1; ; freq++ {
if keys, exists := lfu.frequencyMap[freq]; exists && len(keys) > 0 {
key := keys[0]
lfu.frequencyMap[freq] = keys[1:]
delete(lfu.cache, key)
break
}
}
}
// 缓存策略工厂
type CacheStrategyFactory struct{}
func (f *CacheStrategyFactory) CreateCacheStrategy(strategy string, capacity int) CacheStrategy {
switch strategy {
case "lru":
return NewLRUCache(capacity)
case "lfu":
return NewLFUCache(capacity)
default:
return nil
}
}
你可以这样使用:
func main() {
factory := &CacheStrategyFactory{}
// 从配置中获取策略,这里假设为 "lru"
strategy := "lru"
capacity := 10
cache := factory.CreateCacheStrategy(strategy, capacity)
cache.Put("key1", "value1")
value, exists := cache.Get("key1")
fmt.Printf("Get key1: value=%v, exists=%v\n", value, exists)
}