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)后退出。

它演示了什么

五步流程

下面这段来自 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
				
示例的五步。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

相关