程序员自救转型手记22:从PHP到AI和Golang改用AGENTS.md
时间:2026-07-07 15:39
改用AGENTS md文件,通过@import引用替代原有CLAUDE md。新文件明确技术栈(Go+Gin+GORM+Vue3等)、回答偏好、关键约定(包名、文件名、仅GET POST、GORMGenericsAPI等)及后端四层泛型架构、配置热重载、路由与模型自动注册、Token认证、点选验证码、统一响应;前端路径别名、静态路由自动加载、Pinia状态管
上一期聊了网络请求封装的优化,这期来搞定一件事:切换到 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: on
1. .claudeCLAUDE.md
❯ 2. L AGENTS.md@-imported
3. User memorySa ved in ~/.claude/CLAUDE.md
4. Project memory Checked in at ./CLAUDE.md
5. 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 在当前代码库中工作时提供一个方向指引。
技术栈
后端:Go 1.25、Gin、GORM、PostgreSQL;前端:Vue 3、Element Plus、TypeScript、Vite、Pinia、Axios。
回答偏好
回复用中文;遇到有多个实现方案时,把选项列出来,让用户自己选,不要直接替用户做决定。
关键约定
- **包名**:全小写、单数、无下划线(handler、service)
- **文件名**:全小写、下划线分隔(user_service.go)
- **只使用 GET 和 POST 请求方式**:大多数 CDN 或全站加速服务对 PUT、DELETE 的兼容性不太好
- **GORM**:统一使用 Generics API(gorm.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 来做配置管理,加载顺序如下,后加载的会覆盖前面的:
1. config/*.yaml:glob 匹配所有 yaml 文件,按文件名顺序 merge
2. 根目录下的 .env.yaml(如果存在,会覆盖上面的配置,这个文件已 gitignore,不会入库)
3. 环境变量(AutomaticEnv)
支持配置热重载,通过 OnConfigChange 和 WatchConfig 实现,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")触发 init,然后 router.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() 函数。
身份令牌(Token)
internal/infra/token/token.go 定义了 Driver 接口和全局单例 Manager(),通过 sync.Once 懒初始化,根据 token.driver 配置选择驱动,目前只有 database 驱动。Token 入库前会做 SHA256,校验和删除时也同样哈希后再比对。认证中间件在 middleware/admin_auth.go 里,有 AdminAuth(强制登录认证)和 AdminAuthOptional(可选登录认证),从 Authorization: Bearer
中提取 token,校验后把 AdminSession 注入到 context 里。
点选验证码(Click Captcha)
internal/infra/captcha/click.go 是核心特色模块之一:在背景图上绘制中文、大写字母、图标元素,带碰撞检测与混淆元素;用户按顺序点击,服务端比对元素列表和坐标容差。captcha.yaml 控制元素类型、数量、过期时间、字体路径、背景图目录、图标目录及图标中英文名映射。bootstrap() 首次调用加载中文字符池与图标元数据,每次 Create 时顺带清理过期记录。Check(req, deleteOnSuccess) 的第二参数控制验证成功是否删除记录——预验场景传 false,登录场景传 true。
统一响应
internal/response/response.go 定义了响应体结构 {code, message, time, data},code=0 表示成功、code=1 表示失败(均返回 HTTP 200)。有两种用法:函数式选项 response.Success(c, response.WithData(x)) 或链式 response.New(c).Code(...).Message(...).Send(),日常使用函数式选项用法。
前端(web/)
路径别名与入口
/@/ 映射到 src/(tsconfig 的 paths 与 vite 的 resolve.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。新增静态路由只需在该目录加文件。
状态管理(Pinia)
src/stores/ 下包括:config(站点/语言/布局配置,持久化)、adminInfo(管理员信息含 token,持久化)、menu、na vTab、ref。持久化 key 集中在 src/stores/constant/cacheKey.ts。
请求封装(src/utils/request.ts)
axios 实例的 baseURL 取自 VITE_AXIOS_BASE_URL。拦截器特性如下:
- **大小写转换**:请求时 camelCase 转为 snake_case,响应时 snake_case 转为 camelCase(convertCase !== false 时生效,FormData/URLSearchParams/Blob 不转换)
- **重复请求取消**:默认开启(cancelDuplicate !== false),按 method、url、params、data 生成 key,新请求会 abort 旧请求
- **loading**:loading=true 时显示全屏 loading(计数式,支持并发)
- **Bearer token**:自动从 useAdminInfo().token 注入 Authorization
- 新增 API 请求函数放在 src/api/,参考 api/admin/index.ts、api/common.ts
