golang数据库迁移管理工具插件goose的使用

Golang数据库迁移管理工具插件Goose的使用

Goose是一个数据库迁移工具,既可以作为CLI使用,也可以作为库集成到Go应用中。

安装

go install github.com/pressly/goose/v3/cmd/goose@latest

对于macOS用户,也可以通过Homebrew安装:

brew install goose

基本使用

创建迁移文件

# 创建SQL迁移文件
$ goose create add_some_column sql
$ Created new file: 20170506082420_add_some_column.sql

# 使用顺序编号创建迁移文件
$ goose -s create add_some_column sql
$ Created new file: 00001_add_some_column.sql

# 创建Go迁移文件
$ goose create fetch_user_data go
$ Created new file: 20170506082421_fetch_user_data.go

应用迁移

# 应用所有可用迁移
$ goose up
$ OK    001_basics.sql
$ OK    002_next.sql
$ OK    003_and_again.go

# 迁移到特定版本
$ goose up-to 20170506082420
$ OK    20170506082420_create_table.sql

# 应用单个迁移
$ goose up-by-one
$ OK    20170614145246_change_type.sql

回滚迁移

# 回滚单个迁移
$ goose down
$ OK    003_and_again.go

# 回滚到特定版本
$ goose down-to 20170506082527
$ OK    20170506082527_alter_column.sql

# 回滚所有迁移(谨慎使用)
$ goose down-to 0

查看状态

$ goose status
$   Applied At                  Migration
$   =======================================
$   Sun Jan  6 11:25:03 2013 -- 001_basics.sql
$   Sun Jan  6 11:25:03 2013 -- 002_next.sql
$   Pending                  -- 003_and_again.go

查看当前版本

$ goose version
$ goose: version 002

环境变量配置

可以通过环境变量配置Goose:

export GOOSE_DRIVER=DRIVER
export GOOSE_DBSTRING=DBSTRING
export GOOSE_MIGRATION_DIR=MIGRATION_DIR
export GOOSE_TABLE=TABLENAME

或者使用.env文件:

GOOSE_DRIVER=postgres
GOOSE_DBSTRING=postgres://admin:admin@localhost:5432/admin_db
GOOSE_MIGRATION_DIR=./migrations
GOOSE_TABLE=custom.goose_migrations

迁移文件类型

SQL迁移

SQL迁移文件示例:

-- +goose Up
CREATE TABLE post (
    id int NOT NULL,
    title text,
    body text,
    PRIMARY KEY(id)
);

-- +goose Down
DROP TABLE post;

Go迁移

Go迁移文件示例:

package migrations

import (
	"database/sql"

	"github.com/pressly/goose/v3"
)

func init() {
	goose.AddMigration(Up, Down)
}

func Up(tx *sql.Tx) error {
	_, err := tx.Exec("UPDATE users SET username='admin' WHERE username='root';")
	if err != nil {
		return err
	}
	return nil
}

func Down(tx *sql.Tx) error {
	_, err := tx.Exec("UPDATE users SET username='root' WHERE username='admin';")
	if err != nil {
		return err
	}
	return nil
}

嵌入式SQL迁移

使用Go 1.16+的embed功能:

package main

import (
    "database/sql"
    "embed"

    "github.com/pressly/goose/v3"
)

//go:embed migrations/*.sql
var embedMigrations embed.FS

func main() {
    var db *sql.DB
    // 设置数据库连接

    goose.SetBaseFS(embedMigrations)

    if err := goose.SetDialect("postgres"); err != nil {
        panic(err)
    }

    if err := goose.Up(db, "migrations"); err != nil {
        panic(err)
    }

    // 运行应用
}

完整示例

1. 初始化项目

mkdir myproject
cd myproject
go mod init myproject
go get github.com/pressly/goose/v3

2. 创建迁移目录和文件

mkdir -p migrations
goose create init sql

编辑生成的迁移文件(migrations/xxxx_init.sql):

-- +goose Up
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    username VARCHAR(255) NOT NULL UNIQUE,
    email VARCHAR(255),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- +goose Down
DROP TABLE users;

3. 创建main.go

package main

import (
	"database/sql"
	"log"

	_ "github.com/lib/pq"
	"github.com/pressly/goose/v3"
)

func main() {
	// 设置数据库连接
	db, err := sql.Open("postgres", "user=postgres dbname=postgres sslmode=disable")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// 运行迁移
	if err := goose.SetDialect("postgres"); err != nil {
		log.Fatal(err)
	}

	if err := goose.Up(db, "migrations"); err != nil {
		log.Fatal(err)
	}

	log.Println("Migrations applied successfully!")
}

4. 运行迁移

go run main.go

注意事项

  1. 对于MySQL,需要在连接字符串中添加parseTime=truemultiStatements=true参数
  2. 迁移文件必须以数字开头,后跟下划线
  3. Go迁移文件不能以*_test.go结尾
  4. 建议采用混合版本控制策略,开发时使用时间戳,生产环境使用顺序编号

Goose支持多种数据库,包括Postgres、MySQL、SQLite、MSSQL等,是一个功能强大且灵活的数据库迁移工具。


更多关于golang数据库迁移管理工具插件goose的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang数据库迁移管理工具插件goose的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Goose - Golang数据库迁移管理工具使用指南

Goose是一个简单而强大的数据库迁移工具,支持Go语言编写迁移脚本。它类似于Ruby的ActiveRecord迁移或Python的Alembic,但专为Go设计。

安装Goose

go get -u github.com/pressly/goose/v3/cmd/goose

基本使用

1. 初始化迁移目录

goose -dir=migrations create init_schema sql

这会在migrations目录下创建两个文件:

  • XXXXXX_init_schema_up.sql - 升级迁移
  • XXXXXX_init_schema_down.sql - 回滚迁移

2. 编写迁移文件

up.sql - 升级操作

-- +goose Up
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    username TEXT UNIQUE NOT NULL,
    email TEXT UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT NOW()
);

-- +goose StatementBegin
CREATE OR REPLACE FUNCTION update_timestamp()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- +goose StatementEnd

down.sql - 回滚操作

-- +goose Down
DROP TABLE IF EXISTS users;
DROP FUNCTION IF EXISTS update_timestamp;

3. 运行迁移

goose -dir=migrations postgres "user=postgres dbname=mydb sslmode=disable" up

Go代码集成

你也可以在Go代码中直接使用Goose:

package main

import (
	"database/sql"
	"log"

	_ "github.com/lib/pq"
	"github.com/pressly/goose/v3"
)

func main() {
	db, err := sql.Open("postgres", "user=postgres dbname=mydb sslmode=disable")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// 设置迁移目录
	goose.SetBaseFS(nil) // 如果需要嵌入迁移文件,可以设置embed.FS
	migrationDir := "migrations"

	// 运行迁移
	if err := goose.Up(db, migrationDir); err != nil {
		log.Fatal(err)
	}

	// 或者运行特定版本
	// if err := goose.UpTo(db, migrationDir, 20230801000000); err != nil {
	// 	log.Fatal(err)
	// }
}

高级功能

1. 使用Go迁移脚本

除了SQL,Goose还支持Go编写的迁移脚本:

goose -dir=migrations create add_user_columns go

这会生成一个Go模板文件:

package migrations

import (
	"database/sql"
	"github.com/pressly/goose/v3"
)

func init() {
	goose.AddMigration(upAddUserColumns, downAddUserColumns)
}

func upAddUserColumns(tx *sql.Tx) error {
	// 升级逻辑
	_, err := tx.Exec("ALTER TABLE users ADD COLUMN age INT")
	return err
}

func downAddUserColumns(tx *sql.Tx) error {
	// 回滚逻辑
	_, err := tx.Exec("ALTER TABLE users DROP COLUMN age")
	return err
}

2. 状态检查

goose -dir=migrations postgres "user=postgres dbname=mydb sslmode=disable" status

3. 回滚迁移

# 回滚一步
goose -dir=migrations postgres "user=postgres dbname=mydb sslmode=disable" down

# 回滚到特定版本
goose -dir=migrations postgres "user=postgres dbname=mydb sslmode=disable" down-to 20230801000000

最佳实践

  1. 版本控制:确保迁移文件在版本控制系统中
  2. 原子性:每个迁移应该是原子的,要么完全成功,要么完全失败
  3. 测试:在生产环境运行前,先在测试环境测试迁移
  4. 顺序:迁移应该按照时间顺序执行,不要修改已提交的迁移文件
  5. 回滚:确保每个up迁移都有对应的down迁移

Goose是一个简单但功能强大的工具,可以帮助你管理数据库模式的变化,特别是在团队协作和持续集成/部署环境中非常有用。

回到顶部