Skip to content

go migrate

gormigrate 是一个为 Go 中的 GORM 提供的迁移工具库,帮助开发者在数据库中执行版本控制和迁移操作。其设计目标是简化和自动化数据库架构变更的管理。下面我会详细讲解 gormigrate 的用法,从 API 设计到具体的使用流程。

一、API 设计

gormigrate 的设计围绕迁移(Migration)进行,每个迁移有两个核心概念:UpDown,分别表示应用迁移和回滚迁移。

1. gormigrate.Migration 结构体

每个迁移都需要一个 Migration 结构体,该结构体包含了 IDUpDown 方法:

go
type Migration struct {
    ID   string // 唯一标识迁移的 ID
    Up   func(*gorm.DB) error // 应用迁移的操作
    Down func(*gorm.DB) error // 回滚迁移的操作
}
  • ID: 迁移的唯一标识符,通常使用时间戳来确保唯一性。
  • Up: 一个函数,接受一个 *gorm.DB 对象,用来定义数据库的变更操作。
  • Down: 一个函数,定义了回滚操作,通常是撤销 Up 中的操作。

2. gormigrate 结构体

gormigrate 结构体用于管理迁移操作,它的主要方法包括:

  • New:创建新的 gormigrate 实例。
  • Migrate:应用所有未执行的迁移。
  • RollbackLast:回滚最后一次迁移。
  • Rollback:根据迁移 ID 回滚指定迁移。
go
type Gormigrate struct {
    DB      *gorm.DB
    Options Options
    Migrations []*Migration
}

func New(db *gorm.DB, options Options, migrations []*Migration) *Gormigrate
func (g *Gormigrate) Migrate() error
func (g *Gormigrate) RollbackLast() error
func (g *Gormigrate) Rollback(migrationID string) error
  • DB: 连接的数据库实例。
  • Options: 配置选项,如是否自动提交。
  • Migrations: 迁移列表,每个迁移都是一个 Migration 对象。

二、gormigrate 使用流程

以下是一个完整的使用流程,包括如何定义迁移、如何应用迁移、如何回滚迁移等。

1. 安装 gormigrate

首先,确保已经安装了 gormigrate

bash
go get github.com/go-gormigrate/gormigrate/v2

2. 初始化数据库连接

通过 gorm 连接到数据库。gormigrate 需要一个 gorm.DB 实例来管理迁移。

go
package main

import (
	"log"

	"github.com/go-gormigrate/gormigrate/v2"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

func main() {
	// 连接到 SQLite 数据库
	db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
	if err != nil {
		log.Fatal(err)
	}

	// 初始化迁移操作
	m := gormigrate.New(db, gormigrate.DefaultOptions, migrations)

	// 执行迁移
	if err := m.Migrate(); err != nil {
		log.Fatalf("迁移失败: %v", err)
	} else {
		log.Println("迁移成功!")
	}
}

3. 定义模型(Model)

首先,我们需要定义要操作的数据库模型。比如,我们定义一个 User 模型:

go
type User struct {
	ID    uint   `gorm:"primarykey"`
	Name  string
	Email string
}

4. 定义迁移(Migration)

接下来,定义迁移,确保数据库结构随着应用的变化而变化。

go
var migrations = []*gormigrate.Migration{
	{
		ID: "20230101010101_create_users_table", // 唯一的迁移 ID
		Up: func(tx *gorm.DB) error {
			// 创建 users 表
			return tx.AutoMigrate(&User{})
		},
		Down: func(tx *gorm.DB) error {
			// 回滚:删除 users 表
			return tx.Migrator().DropTable(&User{})
		},
	},
	{
		ID: "20230101010201_add_email_to_users", // 另一个迁移 ID
		Up: func(tx *gorm.DB) error {
			// 给 users 表添加 email 字段
			return tx.Migrator().AddColumn(&User{}, "email")
		},
		Down: func(tx *gorm.DB) error {
			// 回滚:删除 email 字段
			return tx.Migrator().DropColumn(&User{}, "email")
		},
	},
}
  • Up 方法定义了数据库的变更(例如创建表、添加字段等)。
  • Down 方法定义了回滚时执行的操作(例如删除表、删除字段等)。

5. 应用迁移(Migrate)

通过调用 Migrate 方法,gormigrate 会执行所有未执行过的迁移,并记录迁移历史。

go
if err := m.Migrate(); err != nil {
	log.Fatalf("迁移失败: %v", err)
} else {
	log.Println("迁移成功!")
}

6. 回滚迁移(Rollback)

gormigrate 允许回滚迁移,撤销已经执行的迁移操作。你可以回滚最后一次迁移,或者指定迁移 ID 回滚。

回滚最后一次迁移:
go
if err := m.RollbackLast(); err != nil {
	log.Fatalf("回滚迁移失败: %v", err)
} else {
	log.Println("回滚成功!")
}
回滚指定迁移:
go
if err := m.Rollback("20230101010101_create_users_table"); err != nil {
	log.Fatalf("回滚迁移失败: %v", err)
} else {
	log.Println("回滚成功!")
}

7. 查看迁移历史

gormigrate 会在数据库中自动创建一个 gormigrate 表,用于记录迁移的历史和状态。你可以查询这个表来查看已应用的迁移 ID。

三、迁移的进阶使用

1. 迁移 ID 的命名规范

  • 迁移 ID 通常采用时间戳格式(如 20230101010101),以保证唯一性。
  • 可以使用简单的描述性命名,如 create_users_tableadd_email_to_users 等。

2. 迁移的顺序控制

gormigrate 会根据 ID 字段的字母顺序来确定迁移的顺序。通常建议使用时间戳或递增数字来确保迁移的顺序正确。

3. 批量迁移与回滚

可以将多个迁移批量管理和执行,gormigrate 会按顺序执行每个迁移,且每个迁移都可以包含不同的数据库操作(例如创建表、添加索引、修改字段等)。

go
var migrations = []*gormigrate.Migration{
	// 多个迁移操作
}

四、总结

  • gormigrate 是 GORM 的数据库迁移工具,用于帮助开发者管理数据库的版本控制。
  • 迁移的核心概念是 UpDown,分别表示应用和回滚迁移。
  • 迁移 ID 通常采用时间戳或递增数字来确保唯一性。
  • 通过 Migrate() 方法应用迁移,通过 Rollback()RollbackLast() 回滚迁移。

gormigrate 简化了数据库结构的管理,使得团队开发中能更好地追踪和回滚数据库变更,保持代码与数据库结构的同步。

cli

gormigrate 本身并不直接提供命令行工具(CLI)来执行迁移操作。不过,你可以结合 gormigrate 和其他工具(例如 cobra)来构建自己的 CLI 工具,或者通过脚本和自定义命令行来自动化迁移操作。gormigrate 提供的是一个 Go 语言库,它主要通过编程接口来管理数据库迁移。

1. 使用 gormigrate 构建 CLI 工具

你可以通过结合 gormigrate 和流行的 CLI 库(例如 cobra)来创建一个自定义的命令行工具。这通常涉及到定义命令来应用迁移、回滚迁移以及查看迁移状态。

1.1 安装 cobra

cobra 是 Go 语言中流行的 CLI 库,它可以帮助你轻松地创建命令行程序。你可以使用以下命令安装 cobra

bash
go get -u github.com/spf13/cobra

1.2 示例:创建一个简单的 CLI 工具来执行数据库迁移

假设我们想创建一个 CLI 工具,可以执行迁移(migrate)和回滚(rollback)操作。

1.2.1 设置命令行结构

首先,定义一个 cli 包和一个用于数据库迁移的命令。

go
package cli

import (
	"fmt"
	"log"

	"github.com/go-gormigrate/gormigrate/v2"
	"github.com/spf13/cobra"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

// 定义数据库迁移命令
func NewMigrateCmd() *cobra.Command {
	return &cobra.Command{
		Use:   "migrate",
		Short: "执行数据库迁移",
		Run: func(cmd *cobra.Command, args []string) {
			// 连接数据库
			db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
			if err != nil {
				log.Fatal(err)
			}

			// 定义迁移操作
			m := gormigrate.New(db, gormigrate.DefaultOptions, migrations)

			// 执行迁移
			if err := m.Migrate(); err != nil {
				log.Fatalf("迁移失败: %v", err)
			} else {
				fmt.Println("迁移成功!")
			}
		},
	}
}

// 回滚迁移命令
func NewRollbackCmd() *cobra.Command {
	return &cobra.Command{
		Use:   "rollback",
		Short: "回滚数据库迁移",
		Run: func(cmd *cobra.Command, args []string) {
			// 连接数据库
			db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
			if err != nil {
				log.Fatal(err)
			}

			// 初始化迁移工具
			m := gormigrate.New(db, gormigrate.DefaultOptions, migrations)

			// 回滚迁移
			if err := m.RollbackLast(); err != nil {
				log.Fatalf("回滚迁移失败: %v", err)
			} else {
				fmt.Println("回滚成功!")
			}
		},
	}
}

// 定义迁移操作
var migrations = []*gormigrate.Migration{
	{
		ID: "20230101010101_create_users_table",
		Up: func(tx *gorm.DB) error {
			return tx.AutoMigrate(&User{})
		},
		Down: func(tx *gorm.DB) error {
			return tx.Migrator().DropTable(&User{})
		},
	},
}

type User struct {
	ID    uint   `gorm:"primarykey"`
	Name  string
	Email string
}
1.2.2 设置 main 函数

然后,在 main.go 文件中,将这些命令注册到 cobra 应用程序中:

go
package main

import (
	"fmt"
	"log"
	"os"

	"github.com/spf13/cobra"
	"yourproject/cli"
)

func main() {
	var rootCmd = &cobra.Command{Use: "db"}

	// 注册 migrate 和 rollback 命令
	rootCmd.AddCommand(cli.NewMigrateCmd())
	rootCmd.AddCommand(cli.NewRollbackCmd())

	// 执行命令
	if err := rootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}
1.2.3 编译并运行

现在你可以通过以下命令构建并运行这个 CLI 工具:

bash
go build -o dbcli main.go

执行数据库迁移:

bash
./dbcli migrate

回滚数据库迁移:

bash
./dbcli rollback

2. gormigrateCLI 的配合优势

结合 gormigrate 和自定义的 CLI 工具,你可以实现以下功能:

  • 应用迁移:通过命令行工具执行数据库迁移,自动执行 Up 方法中的数据库更改。
  • 回滚迁移:通过命令行工具回滚上一次迁移或指定的迁移,撤销之前的数据库更改。
  • 灵活的迁移管理:通过 CLI 管理和追踪不同环境下的数据库变更,例如生产环境、开发环境和测试环境的迁移。
  • 版本控制:CLI 工具可以帮助你追踪和管理数据库架构的版本,确保团队成员在不同的开发阶段有相同的数据库结构。

3. 其他工具结合使用

  • goose:如果你需要更复杂的迁移工具,goose 也是一个 Go 语言的数据库迁移工具,它内置了 CLI 支持,可以用于管理数据库迁移。
  • migratemigrate 是另一个流行的数据库迁移库,它提供了丰富的 CLI 功能,可以很方便地执行迁移操作。可以参考它的实现,结合自己的需求实现 CLI 功能。

4. 总结

虽然 gormigrate 本身没有内建的 CLI,但它非常适合与 Go 的 CLI 库(如 cobra)结合使用,通过编程的方式构建自己的 CLI 工具,轻松管理数据库迁移。通过这种方式,你可以在不同的环境中自动化执行数据库迁移、回滚操作,并有效地管理数据库的版本控制。