Go (Golang) 数据库迁移:如何管理数据模式
在使用 Go 开发应用程序时,迟早需要更改数据库结构:添加新表、修改现有列、创建索引。在不同环境(本地开发环境、预发布环境、生产环境)下手动执行 SQL 脚本会导致错误和不同步。解决方案是——数据库迁移 (database migrations)。
在 Go 生态系统中,有几个成熟的库用于管理迁移。在本文中,我们将详细介绍三种最流行的工具:golang-migrate/migrate、pressly/goose 和 rubenv/sql-migrate。您将了解如何安装、配置和使用它们,并学习最佳实践。
什么是迁移以及为什么需要它们?
迁移是一个(或一组)文件,包含用于更改数据库模式的 SQL 命令。每个迁移都有一个唯一标识符(通常是时间戳或编号)和两个方向:up(应用更改)和 down(回滚更改)。
使用迁移的主要优势:
- 模式版本控制——更改历史与代码一起存储在仓库中。
- 可重现性——在所有环境中进行相同的更改。
- 更改回滚——能够快速恢复到以前的模式版本。
- 团队协作——开发人员不会互相覆盖更改。
1. golang-migrate/migrate
Go 中最流行的迁移库。支持 PostgreSQL、MySQL、SQLite、MongoDB 和许多其他数据库。
安装
go get -u github.com/golang-migrate/migrate/v4go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@latest迁移结构
创建一个 migrations 文件夹,并添加格式为 {timestamp}_{title}.{direction}.sql 的文件:
migrations/ 000001_create_users_table.up.sql 000001_create_users_table.down.sql 000002_add_email_column.up.sql 000002_add_email_column.down.sql迁移示例 (up)
-- 000001_create_users_table.up.sqlCREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL, created_at TIMESTAMP DEFAULT NOW());迁移示例 (down)
-- 000001_create_users_table.down.sqlDROP TABLE IF EXISTS users;从 Go 代码应用迁移
package main
import ( "github.com/golang-migrate/migrate/v4" _ "github.com/golang-migrate/migrate/v4/database/postgres" _ "github.com/golang-migrate/migrate/v4/source/file")
func main() { m, err := migrate.New( "file://migrations", "postgres://localhost:5432/mydb?sslmode=disable") if err != nil { panic(err) } if err := m.Up(); err != nil && err != migrate.ErrNoChange { panic(err) }}2. pressly/goose
Goose 是一个轻量级且快速的工具,也支持用 Go(不仅仅是 SQL)编写迁移。非常适合需要代码端逻辑的项目。
安装
go get github.com/pressly/goose/v3/cmd/goose创建迁移
goose create create_users_table sql将创建一个类似 20250101120000_create_users_table.sql 的文件。内容如下:
-- +goose UpCREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL);
-- +goose DownDROP TABLE IF EXISTS users;Go 迁移(高级选项)
Goose 允许编写迁移