从 PHP 到 AI + Golang,程序员自救转型手记(二十九):token 过期清理、获取实例的方法名称规范统一
这是一个系列 Blog作者将以一个 PHP 全栈工程师的身份利用 AI 工具claude code、codex、deepseek、豆包等从零开始学习 golang 语言并最终完成 ai-go-admingithub | gitee开源项目的制作全程记录分享。在上一期我们进行了 “管理员登录态保持优化、验权中间件”本期将完成token 过期清理、获取实例的方法名称规范统一token 过期清理突然发现我们的 token 管理器没有过期清理机制这会导致 tokens 表无限膨胀现在对 token 清理功能进行设计采用写时附带清理模式即每次写入token时都检查一下是否有过期token可以清理清理时机仅为Create时Get和Check这类高频调用的方法不触发清理请求方法使用独立context不受请求生命周期影响AI 在驱动层创建了ClearExpired方法然后在 token 管理器的Create方法中调用核心代码如下internal\infra\token\driver\database.go 文件func(d*Database)ClearExpired(ctx context.Context)error{_,err:gorm.G[model.Token](database.DB()).Where(expired_at ?,time.Now()).Delete(ctx)returnerr}internal\infra\token\token.go 文件func(m*Manager)Create(ctx context.Context,token*model.Token)error{// 清理过期令牌Create 为低频操作使用独立 context 不受请求生命周期影响m.cleanExpired()token.Tokensha256Hex(token.Token)returnm.driver.Create(ctx,token)}func(m*Manager)cleanExpired(){_m.driver.ClearExpired(context.Background())}可以看到cleanExpired的封装很多余直接在Create调用驱动的ClearExpired不就可以了这里还是尊重一下 AI问它是不是要改合理。理由1. cleanExpired()只被 Create 调用一次是单点使用的薄包装仅做用 Background 调一次并忽略错误抽象价值低2. Go 社区倾向避免不必要的间接层YAGNI单次调用的简单委托直接内联更清晰3. captcha 的 cleanExpired 有存在意义——它是包级函数且 bootstrap()里还耦合了 bootstrapOnce 资源加载token 这个 cleanExpired 只是一行委托没有额外逻辑去掉合理可能的疑问Qtoken不同于只需要 5 分钟有效期的验证码有的读者会认为我们需要做一定的延后清理比如未来有可能需要在短时间内对已过期 token 给与友好提示比如提示登录态已过期而不是直接提示请登录A本项目的AdminAuth中间件内只要在请求时发送了token值那么无论 token 是没查到还是过期都统一提示身份认证令牌失效请重新登录所以可以在 token 过期时就立即删除没差别。获取实例的方法名称统一internal\infra\config\config.go文件配置管理使用Viper方法获取全局实例使用Get方法获取配置internal\infra\database\database.go数据库初始化使用DB方法获取全局数据库实例internal\infra\token\token.gotoken管理器使用Instance方法获取全局实例我直接问了 AI我考虑统一一下获取实例的方法名称或总结一个命名风格你觉得如何做比较好按返回物命名DB()、Client()、Config()等在Go高星仓库中很常见例如很多项目用db.GetDB()或database.DB()。考虑到你们项目里config比较特殊——它同时暴露了解析后的配置结构体Get()和原始viper引擎Viper()——如果强行把三个都统一成同一个名字反而会让config的语义变模糊。建议只把token.Instance()改成token.Manager()避免token.Instance()与其他包风格割裂。分析和总结的不错接下来就按第 3 点修改直接让 CC 改好就行了。