go-cache 初始化 panic 因参数为负或零:defaultExpiration 应用 cache.NoExpiration 而非 0,cleanupInterval 必须大于 0;Set 总覆盖,SetDefault 仅 key 不存在时写入;Get 返回 (nil, false) 多因并发未加锁或存引用类型;无容量限制与淘汰策略,易 OOM。

go-cache 初始化时为什么总 panic:“invalid memory address”
因为 cache.New 的两个参数不能为负数,但很多人直接传 0 或负值,比如写成 cache.New(0, 0) —— 这会触发内部 time.Duration 转换失败,导致 nil 指针解引用。
- 第一个参数是默认过期时间(
defaultExpiration),设为cache.NoExpiration表示永不过期,别用0 - 第二个参数是清理间隔(
cleanupInterval),必须 > 0;设为0就不启动后台 goroutine,但传负数或0会 panic - 正确写法:
cache.New(5*time.Minute, 1*time.Minute)或cache.New(cache.NoExpiration, 10*time.Second)
Set 和 SetDefault 的行为差异在哪
Set 总是覆盖,SetDefault 只在 key 不存在时才写入 —— 但注意:它不检查 value 是否为空,只看 key 是否已存在。
-
Set("user:123", user, cache.DefaultExpiration):不管之前有没有,都更新 -
SetDefault("user:123", user):仅当 key 完全没被 Set 过(包括已过期被删掉的)才生效 - 如果想“有则跳过、无则设且带过期”,只能自己加
Get判断,go-cache不提供 CAS 类型操作
Get 返回 (nil, false) 但明明刚 Set 过,怎么回事
常见于并发读写没加锁,或者误把指针当值存 —— go-cache 是值拷贝,不是引用缓存。
- 如果你存的是
&myStruct,Get 出来还是那个地址,但原结构体可能已被 GC 或改写 - 更隐蔽的坑:存了 map/slice/chan 等引用类型,后续修改原变量会“意外”影响缓存内容(因为它们共享底层数据)
- 建议统一存不可变结构体或深拷贝后的值;调试时可打印
fmt.Printf("%p", &v)看地址是否一致
为什么本地缓存用了 go-cache 还是扛不住突发流量
因为 go-cache 是纯内存、无淘汰策略的 LRU —— 它只靠过期时间和定时清理,不控制总大小,也不限 key 数量。
立即学习“go语言免费学习笔记(深入)”;
- 高写入场景下,内存持续上涨,GC 压力大,甚至 OOM
- 没有最大容量限制,
Set永远成功,不会像bigcache那样丢老数据腾空间 - 如果需要容量控制,要么自己封装一层计数 + 删除逻辑,要么换
lru或fastcache库
真正难处理的从来不是“怎么存”,而是“什么时候删、删哪些、删完怎么降级”。go-cache 把这部分交给你手动兜底。










