从 PHP 到 AI + Golang,程序员自救转型手记(二十二):改用 AGENTS.md
这是一个系列 Blog作者将以一个 PHP 全栈工程师的身份利用 AI 工具claude code、codex、deepseek、豆包等从零开始学习 golang 语言并最终完成 ai-go-mallgithub | gitee开源项目的制作全程记录分享。在上一期我们进行了 “网络请求封装优化”本期将完成改用 AGENTS.md改用 AGENTS.md离上次更新CLAUDE.md已经过去很长时间了期间新增了非常多的功能本次我直接将现有的CLAUDE.md删除使用 CC 的/init命令来重新生成。生成后我新建了/AGENTS.md文件毕竟这才是最通用的然后于.claude/CLAUDE.md内只写一行import ../AGENTS.md即可。验证为了验证CLAUDE.md中的引用有效因为各个版本的语法不同我们可以使用/memory命令如下我们可以明确看到AGENTS.md -imported字样Memory Auto-memory: on1. .claude\CLAUDE.md ❯2. L AGENTS.md -imported3. User memory Savedin~/.claude/CLAUDE.md4. Project memory Checkedinat ./CLAUDE.md5. Open auto-memory folder Learn more: https://code.claude.com/docs/en/memory Enter to confirm · Esc to cancel全新的 AGENTS.md/init后人工整理了很久在其中简要描述了后端的技术栈、分层结构、配置自动加载、路由自动注册、模型自动迁移、身份令牌Token、点选验证码Click Captcha、统一响应前端的路径别名与入口、路由自动加载、状态管理、请求封装部分未来还会变动的模块暂时没有写进来以下内容为确保显示效果这里将标题等级做了修改AGENTS.md本文件为 AGENTS 在当前代码库中工作时提供指导。技术栈后端Go1.25 Gin GORM PostgreSQL前端Vue3 Element Plus TypeScript Vite Pinia Axios回答偏好回复使用中文遇到有多种实现方案时列出选项让我选择而不是直接选一种关键约定包名全小写、单数、无下划线handler、service文件名全小写、下划线分隔user_service.go只使用 GET 和 POST 请求方式大多数 CDN/全站加速 服务对 PUT、DELETE 兼容性差GORM使用GORM的Generics APIgorm.G[Model](db)....而不是Traditional API且在使用Generics API时一般应直接使用全局 db 实例internal\infra\database\database.go中的DB可获取调用操作方法时再传递合适的 ctx 即可避免 stutter包名已经表达的含义结构体 / 函数不要再重复如admin.AdminService改用admin.Service后端分层结构核心应用架构为泛型驱动的四层架构模式internal/Handler控制器→ Service业务逻辑→ Repository数据访问→ Model数据模型。前三层均有泛型基类对应目录的base.go文件新增子模块时先嵌入再追加自定义方法。配置自动加载internal/infra/config/config.go使用 viper按以下顺序合并后者覆盖前者config/*.yamlglob 全部 yaml按文件名顺序 MergeInConfig根目录.env.yaml若存在覆盖上述配置已 gitignore不入库环境变量AutomaticEnv支持配置热重载OnConfigChangeWatchConfig通过config.Get()取带读写锁的副本。.env.yaml.example是环境配置模板config/config.yaml是默认配置。新增配置项需同步在Config结构体加字段。路由自动注册internal/router/registry/registry.go维护Routes []func(*gin.Engine)。每个业务路由包在init()中调用registry.Register(...)注册自己router/index.go通过空白导入_ ../router/admin、_ ../router/common触发initrouter.Setup(engine)遍历执行。新增路由模块后需要在router/index.go加空白导入。模型自动迁移internal/model/model.go维护registered []any。各模型文件在init()中调用Register(Admin{})database.Init()调用db.AutoMigrate(model.All()...)。新增模型只需在model包内写init() { Register(X{}) }并创建TableName()函数。身份令牌Tokeninternal/infra/token/token.go定义Driver接口与全局单例Manager()sync.Once懒初始化依据token.driver配置选驱动当前仅database驱动。Token 入库前做SHA256校验/删除时同样哈希后比对。认证中间件middleware/admin_auth.goAdminAuth管理员强制登录认证、AdminAuthOptional管理员可选登录认证从Authorization: Bearer token提取校验后注入AdminSession到 context。点选验证码Click Captchainternal/infra/captcha/click.go是核心特色模块之一在背景图上绘制中文/大写字母/图标元素带碰撞检测与混淆元素用户按顺序点击服务端比对 元素列表 坐标容差。captcha.yaml控制元素类型、数量、过期、字体路径、背景图目录、图标目录及图标中英文名映射。bootstrap()首次调用加载中文字符池与图标元数据每次Create顺带清理过期记录。Check(req, deleteOnSuccess)的第二参控制验证成功是否删记录——预验场景传false登录场景传true。统一响应internal/response/response.go响应体{code, message, time, data}code0成功、code1失败均 HTTP 200。两种用法函数式选项response.Success(c, response.WithData(x))/ 链式response.New(c).Code(...).Message(...).Send()日常使用函数式选项用法。前端web/路径别名与入口//→src/tsconfigpaths与 viteresolve.alias一致。入口src/main.ts注册 pinia带pinia-plugin-persistedstate、router、element-plus、i18n、全局 icon。路由用 hash 模式createWebHashHistory。静态路由自动加载src/router/static.ts用import.meta.glob(./static/**/*.ts, { eager: true })自动收集src/router/static/下所有.ts默认导出RouteRecordRaw或RouteRecordRaw[]合并进staticRoutes。src/router/static/adminBase.ts定义后台基础路由/admin。新增静态路由只需在该目录加文件。状态管理Piniasrc/stores/config站点/语言/布局持久化、adminInfo管理员信息含 token持久化、menu、navTab、ref。持久化 key 集中在src/stores/constant/cacheKey.ts。请求封装src/utils/request.tsaxios 实例 baseURL 取VITE_AXIOS_BASE_URL。拦截器特性大小写转换请求 camelCase → snake_case响应 snake_case → camelCaseconvertCase ! false时生效FormData/URLSearchParams/Blob 不转。重复请求取消默认开启cancelDuplicate ! false按 methodurlparamsdata 生成 key新请求 abort 旧请求。loadingloadingtrue显示全屏 loading计数式支持并发。Bearer token自动从useAdminInfo().token注入Authorization。新增 API 请求函数放src/api/参考api/admin/index.ts、api/common.ts。