「go-zero 是不是不用迁移工具?一般怎么做?类比 Python 的 alembic 又是啥样?」—— 这篇讲清 go-zero 的迁移哲学、主流做法,以及与 Python alembic 的对照。
go-zero 的命令行 goctl 和框架本身都不带数据库迁移(migration)能力。但这不等于「不用迁移」——真实项目表结构会变,迁移照样要做,只是用外部工具(golang-migrate / goose / flyway)或手写 SQL,框架不替你管表结构。
记得住的一句话:go-zero 把「建表权」交还给你(或 DBA),不像 GORM 那样 AutoMigrate 偷偷改表、也不像 Python 那样有框架内建的 alembic。迁移是独立的一环,和 goctl model 生成代码是前后两步、各管各的。
这跟「go-zero 建表与 Model」篇里说的「goctl 不执行 CREATE TABLE」是一脉相承的。
goctl model 是「读表生成代码」,不是「改表」。它假设表已经存在且稳定,只负责把表映射成 Go Model。svc.NewServiceContext 里 conn.Exec("CREATE TABLE IF NOT EXISTS ..."),小规模 demo 能跑,但没有版本号、无法回滚、多实例并发建表有竞态,生产千万别这么干。*.sql,在 MySQL 客户端或 CI 里执行,最直白装工具 → 写迁移文件 → 执行 up。这就是 go-zero 项目里「建表」的标准姿势。
Step 1 · 安装 CLI
go install -tags mysql github.com/golang-migrate/migrate/v4/cmd/migrate@latest
Step 2 · 写迁移文件(up 建表 / down 回滚)
-- 000001_create_user.up.sql CREATE TABLE user ( id BIGINT NOT NULL AUTO_INCREMENT, name VARCHAR(64) NOT NULL DEFAULT '', create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_name (name) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 000001_create_user.down.sql DROP TABLE user;
Step 3 · 执行迁移
migrate -path ./migrations \
-database "mysql://root:password@tcp(127.0.0.1:3306)/test" \
up
进阶 · 嵌进 Go 程序,启动时自动跑(可选)
m, _ := migrate.New("file://migrations", "mysql://root:password@tcp(127.0.0.1:3306)/test") m.Up() // 部署时执行,跑过的有版本记录,不会重复
schema_migrations 表里会记录已跑到哪个版本号——这正是「迁移工具」和「随手执行 SQL」的本质区别:有版本、可追溯、可回滚。SQLAlchemy 生态用 alembic 做迁移,工作流和 golang-migrate 神似,但多了一个「自动生成」能力。
alembic 标准流程
# 1. 初始化(生成 alembic.ini / env.py / versions/) alembic init migrations # 2. 改了 Model 后,自动比对生成迁移脚本 alembic revision -m "add user table" --autogenerate # 3. 执行迁移(按版本号顺序 up) alembic upgrade head # 4. 回滚一个版本 alembic downgrade -1
--autogenerate,能比对 ORM Model 与库结构自动生成迁移;golang-migrate 的 SQL 迁移全手写(go 社区没有等价 ORM 自动比对)。迁移管「表结构」,goctl 管「代码」。两者配合,不重叠。
goctl modelINSTANT / 低峰执行AutoMigrate 自动改表(不推荐上生产管复杂变更)revision --autogenerate + upgrade head,可自动比对 Modelmakemigrations + migrate,最像 alembicgo-zero 不用「框架内建迁移」,但生产项目要用「独立迁移工具」。最小可用是手写 SQL,主流是 golang-migrate(版本化 up/down),类比 Python 的 alembic(多一个 autogenerate)。迁移负责「把表建进库」,goctl model 负责「读表生成代码」——前者在先,后者在后,分工明确。