memcache — JSON 缓存、TTL 与 Touch
pkg/core/memcache 包住 gomemcache,提供 JSON 读写、TTL 与
Touch。它是一个命令行程序,不是 HTTP 服务:没有端口,没有
config.yaml,参数走 flag。测试用进程内假服务,离线可跑。
运行
默认连 localhost:11211,需要一个真实 memcached,用
make dev 起。全部参数:
make dev # 起 memcached(以及其它中间件)
go run ./examples/memcache # 等价于 make example NAME=memcache
go run ./examples/memcache -addrs '10.0.0.1:11211,10.0.0.2:11211' -key other -ttl 5s
memcached 没有 ping
协议本身没有连通性探测,所以
Open 永远不会在启动时失败——
第一条命令才会失败,和 redis 的 Open(先 ping)不同。
失败时程序打印 fatal: 与一行 hint(提示 make dev)后退出。
它演示了什么
- 写入:
SetJSON(key, v, ttl),JSON 序列化后带 TTL 存入。 - 读回:
memcache.GetJSON[session](c, key),包级泛型函数。 - miss 不是错误:未命中返回
(zero, false, nil), 只有网络错误或内容损坏才返回err。 - 只续期不改值:
Touch(key, ttl)延长存活时间,不重写内容。 - 删除幂等:
Delete删一个不存在的 key 也不报错。
五步流程
下面这段来自 examples/memcache/main.go 的主体。
每一步都打印一行结果,所以直接看 stdout 就知道每步的语义。
// 1. Write.
if err := c.SetJSON(*key, want, *ttl); err != nil {
fail(err)
}
fmt.Printf("set %s (ttl=%s)\n", *key, *ttl)
// 2. Read back.
got, ok, err := memcache.GetJSON[session](c, *key)
if err != nil {
fail(err)
}
if !ok {
fail(fmt.Errorf("expected a hit for %s", *key))
}
// 3. A miss is (zero, false, nil), never an error.
if _, ok, err := memcache.GetJSON[session](c, *key+":absent"); err != nil || ok {
fail(fmt.Errorf("expected a miss, got ok=%v err=%v", ok, err))
}
Touch 只续期,读到的值不变;键的 TTL 精度是秒,
所以不要传小于 1s 的 TTL。
flowchart LR
A["SetJSON key ttl"] --> B{"GetJSON"}
B -- hit --> C["返回值 + ok=true"]
B -- miss --> D["零值 + ok=false + err=nil"]
C --> E["Touch 延长 TTL"]
E --> F["Delete"]
F --> G["再读 = miss"]
D --> F
classDef hit fill:#eef7f0,stroke:#2f7d4f,color:#22372a
classDef miss fill:#fdf6f0,stroke:#c8641f,color:#2b2722
class C hit
class D miss
ok=false 加 err=nil,
调用方靠 ok 判断,不靠错误。
验证
用默认参数跑一遍,stdout 大致如下:
$ go run ./examples/memcache
set example:session:42 (ttl=1m0s)
get hit → user_id=42 token=tk-42 at=2026-10-18T09:12:00Z
get miss → ok=false err=nil(miss 不报错)
touch example:session:42 (ttl=2m0s)
delete → 再读是 miss(Delete 删不存在的 key 也不报错)
换 key 或 TTL 重跑:go run ./examples/memcache -key other:key -ttl 5s。
测试
main_test.go 不用真的 memcached:它用一个进程内的假服务
(fakeMemcached),在临时端口上跑一个只实现文本协议的 TCP server,
支持 gets/set/touch/delete——
正好是示例会调用的那几个命令,所以测试完全离线。
测试钉住:写入后读回字段一致;miss 是 (zero, false, nil);
Touch 后仍可读;删除后再读是 miss;删除一个不存在的 key 不报错。
go test ./examples/memcache
相关
- 缓存模式:缓存读写的通用约定。
- examples/redis:带 ping、分布式锁与 Lua 的 redis 后端。
- examples/cache:在 redis 上做并发合并与 TTL 抖动。
- Skill:
skills/matex-setup-memcache/SKILL.md。 - 示例索引。