推荐用 sync.Map 或封装 LRU(如 hashicorp/golang-lru)实现轻量可控本地缓存;sync.Map 适合读多写少无淘汰场景,LRU 支持容量限制与淘汰,可扩展 TTL 和监控。

用 Go 实现本地缓存系统,核心是轻量、可控、无依赖——推荐直接使用 sync.Map 或封装 LRU 缓存(如 github.com/hashicorp/golang-lru),避免过早引入 Redis 等外部组件。关键不在“快”,而在“够用+线程安全+可淘汰”。
用 sync.Map 做简单键值缓存
适合读多写少、无需淘汰策略、生命周期与程序一致的场景(比如配置项、静态映射表)。
- 天然并发安全,不用额外加锁
- 不支持容量限制和自动淘汰,需自行控制 size(例如用原子计数器 + 定期清理)
- 示例:缓存解析后的 JSON 配置
cache.Store("config:v1", configObj)
if val, ok := cache.Load("config:v1"); ok { /* 使用 val */ }
用 lru.Cache 实现带淘汰的内存缓存
更贴近真实业务需求:固定容量、最近最少使用淘汰、支持带 TTL 的封装(需自己扩展)。
- go get github.com/hashicorp/golang-lru
- 初始化时指定容量(如 1000 条),超出自动驱逐旧条目
- 注意:原生 lru.Cache 不带过期时间,如需 TTL,可组合 time.Now() + 自定义结构体存储过期时间,Get 时判断
lru.Add("user:1001", &User{ID: 1001, Name: "Alice"})
if val, ok := lru.Get("user:1001"); ok { /* 类型断言后使用 */ }
封装一个带 TTL 的本地缓存模块
把过期逻辑收拢,对外提供类似 Redis 的 Set/Get 接口,提升复用性。
立即学习“go语言免费学习笔记(深入)”;
- 内部用 lru.Cache 存 key→value,另起 goroutine 定期扫描清理过期项(或惰性清理:Get 时检查)
- 结构体字段建议包含:value interface{}、expireAt time.Time
- Set(key, val, ttl time.Duration) 方法中计算 expireAt = time.Now().Add(ttl)
- Get(key) 返回 (val, found, expired),由调用方决定是否刷新
注意事项和避坑点
- 不要在缓存里存指针指向的可变对象(如 *[]byte),修改原数据会导致缓存内容意外变化
- 大对象(>1MB)缓存要考虑 GC 压力,可考虑 mmap 或分块处理
- sync.Map 在高写场景下性能可能不如 RWMutex + map,压测验证再选型
- 上线前务必加 metrics(命中率、size、平均耗时),用 expvar 或 Prometheus client 暴露指标
基本上就这些。本地缓存不复杂但容易忽略淘汰和并发细节,从 sync.Map 或 lru 开始,按需叠加 TTL 和监控,就能快速跑起来一个稳定可用的模块。










