从 PHP 到 AI + Golang,程序员自救转型手记(三十一):增加 config 模型、数据表自动迁移优化

从 PHP 到 AI + Golang,程序员自救转型手记(三十一):增加 config 模型、数据表自动迁移优化
这是一个系列 Blog作者将以一个 PHP 全栈工程师的身份利用 AI 工具claude code、codex、deepseek、豆包等从零开始学习 golang 语言并最终完成 ai-go-admingithub | gitee开源项目的制作全程记录分享。在上一期我们进行了 “实现管理员注销接口、API 请求函数命名规范”本期将完成增加 config 模型、数据表自动迁移优化增加 config 模型得先把config模型加进来因为站点的名称、备案号这些站点基础配置是存储在里边的未来后台的【系统配置】功能也主要就是管理这个表中的数据。作者之前的项目已经设计过完善的config数据表这里直接将建表 SQL 给它复制过来让 CC 转换为 GORM 模型新建config数据模型基于以下SQL的表结构CREATETABLEconfig(idintUNSIGNEDNOTNULLAUTO_INCREMENTCOMMENTID,namevarchar(30)CHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ciNOTNULLDEFAULTCOMMENT变量名,groupvarchar(30)CHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ciNOTNULLDEFAULTCOMMENT分组,titlevarchar(50)CHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ciNOTNULLDEFAULTCOMMENT变量标题,tipvarchar(100)CHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ciNOTNULLDEFAULTCOMMENT变量描述,typevarchar(30)CHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ciNOTNULLDEFAULTCOMMENT变量输入组件类型,valuelongtextCHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ciNULLCOMMENT变量值,contentlongtextCHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ciNULLCOMMENT字典数据,rulevarchar(100)CHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ciNOTNULLDEFAULTCOMMENT验证规则,extendvarchar(255)CHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ciNOTNULLDEFAULTCOMMENT扩展属性,input_extendvarchar(255)CHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ciNOTNULLDEFAULTCOMMENT输入框扩展属性,allow_deltinyintUNSIGNEDNOTNULLDEFAULT0COMMENT允许删除:0否,1是,weighintNOTNULLDEFAULT0COMMENT权重,PRIMARYKEY(id)USINGBTREE,UNIQUEINDEXname(nameASC)USINGBTREE)ENGINEInnoDBAUTO_INCREMENT1CHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ciCOMMENT系统配置ROW_FORMATDYNAMIC;AI 生成的模型如下funcinit(){Register(Config{})}// Config 系统配置模型typeConfigstruct{IDuintgorm:comment:ID;primarykey;autoIncrement json:idNamestringgorm:comment:变量名;type:varchar(50);uniqueIndex;not null;default: json:nameGroupstringgorm:comment:分组;type:varchar(50);not null;default: json:groupTitlestringgorm:comment:变量标题;type:varchar(50);not null;default: json:titleTipstringgorm:comment:变量描述;type:varchar(100);not null;default: json:tipTypestringgorm:comment:变量输入组件类型;type:varchar(50);not null;default: json:typeValuestringgorm:comment:变量值;type:longtext json:valueContentstringgorm:comment:字典数据;type:longtext json:contentRulestringgorm:comment:验证规则;type:varchar(100);not null;default: json:ruleExtendstringgorm:comment:扩展属性;type:varchar(255);not null;default: json:extendInputExtendstringgorm:comment:输入框扩展属性;type:varchar(255);not null;default: json:input_extendAllowDeluint8gorm:comment:允许删除:0否,1是;not null;default:0 json:allow_delWeighintgorm:comment:权重;not null;default:0 json:weigh}这时候发现了一个问题config表内是有初始数据的而且 GORM 的自动迁移终究不是长久之计只适用于开发环境不支持删除字段、不支持字段改名、字段类型变更风险、无版本记录等。所以此时我就得将 GORM 的自动迁移改为更加适合生产环境的然后再向config表插入数据。数据表自动迁移优化我们需要一个更加适合生产环境的数据表迁移工具最起码得有版本控制看了很多工具工具star数备注https://github.com/golang-migrate/migrate18.7k纯 SQL 驱动的迁移工具不支持通过模型生成 SQL生态第一https://github.com/ariga/atlas8.5k新兴的迁移工具支持通过模型生成 SQL支持的语言和框架很多感觉杂而不精https://github.com/go-gormigrate/gormigrate1.2kstar 太少了其他看过的就不一一列出了感觉golang-migrate/migrate挺好的一个是官方背书二是用户多原生 SQL 驱动也方便 DBA 审核 SQL至于不支持通过模型生成 SQLAI 时代不是问题。接下来做规划如下使用https://github.com/golang-migrate/migrate实现生产级数据库迁移功能项目需要同时支持golang-migrate/migrate的CLI模式和库模式库模式于cmd/migrate/main.go建立自定义命令来执行迁移、回滚、查看状态、创建新的迁移文件于cmd/migrate/migrations建立迁移文件请参考现有模型写好SQL同时支持 CLI 模式和库模式的意思是# 即可以这样执行迁移migrate-databasepostgres://user:passhost:port/dbname?sslmodedisable-pathcmd/migrate/migrations up# 也可以执行项目自定义命令执行迁移tmp/aigo.exe migrate up自定义命令也就是库模式下不需要填写-database和-path参数也不需要单独安装migrate CLI是我最喜欢的模式。CLI 模式其实是天然支持的只要你安装了migrate CLI即可使用安装后能额外执行force、drop等命令。将以上内容发给 CC后续 CC 询问以何种方式实现自定义命令这里选择了spf13/cobra然后库模式下迁移文件以何种方式加载 ❯1. go:embed 内嵌推荐 up/down/status 用 go:embed 内嵌的迁移文件编译后二进制自包含便于部署create 命令按--dir写入磁盘目录。开发时创建后需重新编译才能 up。2. 文件系统路径 所有操作直接读写 cmd/migrate/migrations 目录与 golang-migrate CLI 模式完全一致创建后立即可用。但运行二进制时需能访问到该目录。意思也很简单第一个是内嵌到编译产物内生产直接就能用第二个是文件系统内存储生产要用迁移得先上传文件所以这里当然是选择内嵌。第一轮完成后再将原有项目 config 数据表的数据导出来整理了一下可能会用得上的配置项让 CC 基于该 SQL 生成一个 seed 迁移主要包含站点名称、自定义后台入口、备案号、邮件发送等系统基础配置INSERTINTOconfigVALUES(1,config_group,basic,配置分组,,array,[{\key\:\basic\,\value\:\基础配置\},{\key\:\mail\,\value\:\邮件配置\},{\key\:\config_quick_entrance\,\value\:\快捷配置入口\}],NULL,required,,,0,-1);INSERTINTOconfigVALUES(2,name,basic,站点名称,,string,AI GO ADMIN,NULL,required,,,0,99);INSERTINTOconfigVALUES(3,entrance,basic,自定义后台入口,,string,/admin,NULL,required,,,0,1);INSERTINTOconfigVALUES(4,record_number,basic,域名备案号,,string,渝ICP备8888888号-1,NULL,,,,0,0);INSERTINTOconfigVALUES(5,version,basic,系统版本号,,string,v1.0.0,NULL,required,,,0,0);INSERTINTOconfigVALUES(6,timezone,basic,时区,,string,Asia/Shanghai,NULL,required,,,0,0);INSERTINTOconfigVALUES(7,no_access_ip,basic,禁止访问 IP,禁止访问站点的ip列表一行一个,textarea,NULL,NULL,,,,0,0);INSERTINTOconfigVALUES(8,smtp_server,mail,SMTP 服务器,,string,smtp.com,NULL,,,,0,9);INSERTINTOconfigVALUES(9,smtp_port,mail,SMTP 端口,,string,465,NULL,,,,0,8);INSERTINTOconfigVALUES(10,smtp_user,mail,SMTP 用户,,string,NULL,NULL,,,,0,7);INSERTINTOconfigVALUES(11,smtp_pass,mail,SMTP 密码,,string,NULL,NULL,,,,0,6);INSERTINTOconfigVALUES(12,smtp_verification,mail,SMTP 验证方式,,select,SSL,{\SSL\:\SSL\,\TLS\:\TLS\},,,,0,5);INSERTINTOconfigVALUES(13,smtp_sender_mail,mail,SMTP 发件人邮箱,,string,NULL,NULL,email,,,0,4);INSERTINTOconfigVALUES(14,config_quick_entrance,quick_entrance,快捷配置入口,,array,[],NULL,,,,0,0);完工后人工review发现了以下问题缺少表前缀配置应用cmd\migrate\migrations中的 SQL表名全是admins、tokens这种不带表前缀的但是我们的系统支持表前缀只是默认为空。这里让 AI 在 SQL 中以固定字符串__PREFIX__表示表前缀执行迁移前将该字符串替换为项目数据库配置中的实际表前缀。项目命令规划现在多了一个迁移命令将原来的cmd/api/main.go改名为cmd/serve/serve.go作为单独的服务启动命令然后新增cmd/main.go文件作为统一命令入口从现在起# 启动 API 服务go run cmd/main.go serve# 应用数据库迁移go run cmd/main.go migrate up# 或编译后再运行go build-o./tmp/aigo.exe ./cmd/main.go tmp/aigo.exe serve tmp/aigo.exe migrate up同时serve作为默认命令是可以省略的。同步修改 AGENTS.md / README.md / .air.toml这次对数据迁移做了改动项目启动流程和迁移功能介绍都需要重新写直接让 CC 帮忙完成再人工整理一下。放弃原生的 Migrate CLI 工具https://github.com/golang-migrate/migrate是支持CLI和库双模式的正常情况下我整合了库模式CLI天然就能用此时突然发现原生的Migrate CLI不支持传递表前缀啊这里只能再看看CLI还有那些命令是我们当前不支持的让 CC 全部实现一遍version 和 drop 子命令然后直接放弃CLI模式。