一尘不染

如何将迁移与可执行文件绑定

go

我有一个Go项目,它使用goose进行Mysql迁移。我想将迁移绑定到程序包可执行文件,以便该可执行文件可以独立于任何系统进行部署和使用,类似于JAVA项目中的JAR文件。

Go可以做到这一点吗?


阅读 258

收藏
2020-07-02

共1个答案

一尘不染

如何获得一个可以迁移数据库并工作的文件

  1. 安装

    go get -u github.com/pressly/goose/cmd/goose
    
  2. 制作应用。我基于示例main.go并添加run选项。假设您的项目位于github.com/user/project

        package main

    import (
        "database/sql"
        "flag"
        "log"
        "os"

        "github.com/pressly/goose"

        // Init DB drivers. -- here I recommend remove unnecessary - but it's up to you
        _ "github.com/go-sql-driver/mysql"
        _ "github.com/lib/pq"
        _ "github.com/mattn/go-sqlite3"
        _ "github.com/ziutek/mymysql/godrv"

        // here our migrations will live  -- use your path 
        _ "github.com/user/project/migrations"
    )

    var (
        flags = flag.NewFlagSet("goose", flag.ExitOnError)
        dir   = flags.String("dir", ".", "directory with migration files")
    )

    func main() {
        flags.Usage = usage
        flags.Parse(os.Args[1:])

        args := flags.Args()

        //////
        if len(args) > 1 && args[0] == "run" {
           log.Printf("PROGRAM RUN\n")  //
           ..... 
           os.Exit(0)
        }


        if len(args) > 1 && args[0] == "create" {
            if err := goose.Run("create", nil, *dir, args[1:]...); err != nil {
                log.Fatalf("goose run: %v", err)
            }
            return
        }

        if len(args) < 3 {
            flags.Usage()
            return
        }

        if args[0] == "-h" || args[0] == "--help" {
            flags.Usage()
            return
        }

        driver, dbstring, command := args[0], args[1], args[2]

        switch driver {
        case "postgres", "mysql", "sqlite3", "redshift":
            if err := goose.SetDialect(driver); err != nil {
                log.Fatal(err)
            }
        default:
            log.Fatalf("%q driver not supported\n", driver)
        }

        switch dbstring {
        case "":
            log.Fatalf("-dbstring=%q not supported\n", dbstring)
        default:
        }

        if driver == "redshift" {
            driver = "postgres"
        }

        db, err := sql.Open(driver, dbstring)
        if err != nil {
            log.Fatalf("-dbstring=%q: %v\n", dbstring, err)
        }

        arguments := []string{}
        if len(args) > 3 {
            arguments = append(arguments, args[3:]...)
        }

        if err := goose.Run(command, db, *dir, arguments...); err != nil {
            log.Fatalf("goose run: %v", err)
        }
    }

    func usage() {
        log.Print(usagePrefix)
        flags.PrintDefaults()
        log.Print(usageCommands)
    }

    var (
        usagePrefix = `Usage: goose [OPTIONS] DRIVER DBSTRING COMMAND
    Drivers:
        postgres
        mysql
        sqlite3
        redshift
    Examples:
        goose sqlite3 ./foo.db status
        goose sqlite3 ./foo.db create init sql
        goose sqlite3 ./foo.db create add_some_column sql
        goose sqlite3 ./foo.db create fetch_user_data go
        goose sqlite3 ./foo.db up
        goose postgres "user=postgres dbname=postgres sslmode=disable" status
        goose mysql "user:password@/dbname?parseTime=true" status
        goose redshift "postgres://user:password@qwerty.us-east-1.redshift.amazonaws.com:5439/db"
    status
    Options:
    `

        usageCommands = `
    Commands:
        up                   Migrate the DB to the most recent version available
        up-to VERSION        Migrate the DB to a specific VERSION
        down                 Roll back the version by 1
        down-to VERSION      Roll back to a specific VERSION
        redo                 Re-run the latest migration
        status               Dump the migration status for the current DB
        version              Print the current version of the database
        create NAME [sql|go] Creates new migration file with next version
    `
    )
  1. 创建用于迁移的文件夹:

    mkdir migrations && cd migrations
    
  2. 创建第一个迁移。我们将使用go-style迁移:

    goose mysql "user:password@/dbname?parseTime=true" create init go
    

您将获得00001_init.go带有Go代码的文件。迁移作为SQL命令放入其中。只需根据需要对其进行编辑。

  1. 然后转到主文件夹并构建应用程序:

    cd ..
    

    go build -v -o myapp *.go

  2. 您将获得一个myapp包含所有迁移的文件。要检查将其移动到其他位置,例如移动到/tmp文件夹,然后从那里运行:

    ./myapp mysql "user:password@/dbname?parseTime=true" status
    
  3. 运行您的应用程序:

    ./myapp run
    

结果

您只有一个文件,可用作应用程序本身的迁移工具。所有的迁移都是内置的。在源代码中,它们存储在子包中migrations-易于编辑。

2020-07-02