Go (Golang) 数据库迁移:完整指南
在使用 Go 开发 Web 应用程序时,迟早会需要更改数据库结构:添加新表、修改现有列或创建索引。在不同环境(开发、预发布、生产)中手动执行 SQL 脚本会导致错误和不同步。解决这个问题的方法是数据库迁移。
Go 中有几个成熟的库用于管理迁移。在本文中,我们将详细介绍两个最流行的库:golang-migrate/migrate 和 pressly/goose,并提供使用示例。
什么是迁移以及为什么需要它们?
迁移是一组版本化的 SQL 命令(或 Go 代码),按顺序应用于数据库。每个迁移都有一个唯一标识符(通常是时间戳或编号),并且可以应用(up)或回滚(down)。
主要优点:
- 自动化数据库模式更改
- 可重现性——在任何环境中都能获得相同的结果
- 能够回滚更改
- 将更改历史存储在代码中(对版本控制系统友好)
1. golang-migrate/migrate 库
这是 Go 中最流行的迁移库。支持 PostgreSQL、MySQL、SQLite、MongoDB 等数据库管理系统。迁移可以用纯 SQL 编写,也可以用 Go 编写。
安装
go get -u github.com/golang-migrate/migrate/v4迁移文件结构
文件位于 migrations/ 文件夹中,并按以下模板命名:
{timestamp}_{title}.up.sql{timestamp}_{title}.down.sql示例:
migrations/ 000001_create_users_table.up.sql 000001_create_users_table.down.sql 000002_add_email_to_users.up.sql 000002_add_email_to_users.down.sqlSQL 迁移示例
文件 000001_create_users_table.up.sql:
CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT NOW());文件 000001_create_users_table.down.sql:
DROP 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://user:password@localhost:5432/dbname?sslmode=disable", ) if err != nil { panic(err) }
// 应用所有可用的迁移 (Up) if err := m.Up(); err != nil && err != migrate.ErrNoChange { panic(err) }
// 回滚最后一个迁移 (Down) // if err := m.Steps(-1); err != nil { // panic(err) // }}migrate CLI 工具
还提供了一个命令行工具:
migrate create -ext sql -dir migrations -seq create_users_tablemigrate -path migrations -database "postgres://..." upmigrate -path migrations -database "postgres://..." down 12. pressly/goose 库
Goose 是另一个流行的工具,最初是作为 Ruby on Rails 中 ActiveRecord 迁移的替代品而创建的。支持 SQL 和 Go 迁移,并内置 CLI。
安装
go get -u github.com/pressly/goose/v3文件结构
文件命名为 {timestamp}_{title}.sql(不区分 up/down——全部通过注释放在一个文件中):
migrations/ 20240101120000_create_users_table.sql 20240102150000_add_email_to_users.sql