golang-migrate 必须用预编译二进制安装,因 cgo 依赖导致 go install 失败;迁移文件名须严格为 yyyymmddhhmmss_*.up.sql 格式;go 中 url 驱动名须与导入驱动一致(如 sqlite3://);down 迁移需手动编写且幂等。

golang-migrate 命令行工具必须用二进制安装,go install 会失败
直接 go install github.com/golang-migrate/migrate/v4/cmd/migrate@latest 在多数 Go 环境下会报错或生成不可用的二进制——因为 migrate 的 main 包依赖 cgo(尤其是 SQLite 驱动),而默认 GO111MODULE=on + CGO_ENABLED=0 时编译失败。
正确做法是下载预编译二进制:
- 访问
https://github.com/golang-migrate/migrate/releases,选对应系统(如migrate.linux-amd64.tar.gz) - 解压后把
migrate二进制放到$PATH下(比如/usr/local/bin) - 验证:
migrate -version应输出类似v4.15.1
迁移文件命名必须严格遵循 YYYYMMDDHHMMSS_*.up.sql 格式
golang-migrate 不解析文件内容,只靠文件名排序决定执行顺序。一旦格式错位(比如少一位数字、用了横线代替下划线、.up 写成 up),就会跳过或乱序执行。
常见错误现象:
立即学习“go语言免费学习笔记(深入)”;
-
migrate -path ./migrations -database "sqlite:///db.sqlite" up显示 “no change”,但实际有新文件 - 执行了
20230101000000_add_user.down.sql而不是.up.sql
正确命名示例:
20231015142301_create_posts_table.up.sql 20231015142302_add_published_at_to_posts.up.sql
注意:时间戳建议用当前精确到秒的时间,避免手动拼写;不要用 Git 提交时间或随意编号。
Go 代码里调用 migrate 库时,URL 中 driver 名必须和导入的驱动一致
比如你 import _ "github.com/mattn/go-sqlite3",那么数据库 URL 必须用 sqlite3://,而不是 sqlite:// 或 sqlite6://——后者会导致 unknown driver "sqlite6" (forgotten import?) 错误。
常用 driver 名与 URL 前缀对照:
- PostgreSQL:
postgres://(需import _ "github.com/lib/pq") - MySQL:
mysql://(需import _ "github.com/go-sql-driver/mysql") - SQLite3:
sqlite3://(需import _ "github.com/mattn/go-sqlite3")
URL 示例:sqlite3:///tmp/db.sqlite?_fk=1(SQLite 开启外键很重要,否则 migration 中的 FOREIGN KEY 会被静默忽略)
down 迁移不是自动逆向生成的,必须手写且保证幂等
migrate down 不会根据 .up.sql 反推删除语句。如果你写了 CREATE TABLE,.down.sql 就得写对应的 DROP TABLE;如果 .up.sql 是 ALTER TABLE ADD COLUMN,.down.sql 就得是 ALTER TABLE DROP COLUMN(注意:SQLite 不支持 DROP COLUMN,得用重建表方式)。
容易踩的坑:
- 在 PostgreSQL 中写了
DROP TABLE IF EXISTS users,但没加IF EXISTS,第二次down就报错中断 - MySQL 中用
TEXT类型字段加索引未指定长度,down时删索引成功,但再up失败(因长度限制变化) - 忘记测试
down后再up是否能循环通过(即迁移是否可逆)
真正麻烦的地方不在语法,而在业务约束:比如某次 up 把 email 字段设为 NOT NULL,down 时若已有空值数据,直接改回 NULL 就行;但若 up 还加了唯一索引,down 时就得先删索引再改字段,顺序反了就失败。










