如何使用golang可执行文件绑定迁移

时间:2017-10-31 07:44:39

标签: mysql database go database-migration

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

Golang中是否有相同的功能来完成它?

3 个答案:

答案 0 :(得分:1)

如果您使用Docker,您可以将文件夹放入图像。

如果不是https://github.com/rakyll/statikhttps://github.com/jteeuwen/go-bindata等项目可以提供帮助。

答案 1 :(得分:1)

如果您已经在使用Goose,则可以选择在Go中编写迁移而不是SQL。根据Goose repo中的Go migrations example,当您在此处构建goose二进制文件时,它会将所有*.go二进制文件捆绑到二进制文件中。

这是我构建示例后删除除二进制本身之外的所有文件的输出。嵌入了基于Go的迁移:

2017/10/31 11:22:31     Applied At                  Migration
2017/10/31 11:22:31     =======================================
2017/10/31 11:22:31     Mon Jun 19 21:56:00 2017 -- 00002_rename_root.go

如果您希望使用基于SQL的迁移但又不想承担其他依赖项,则可以将基于SQL的迁移嵌入到*.go文件中作为字符串常量,然后,从go-migrations示例开始,将init阶段添加到main.go,然后将其写入当前目录,然后再继续。

答案 2 :(得分: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
    `
    )
    
  3. 创建迁移文件夹:

    mkdir migrations && cd migrations
    
  4. 创建首次迁移。我们将使用go式样迁移:

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

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

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

    cd ..
    go build -v -o myapp *.go
    
  6. 您将获得一个文件myapp,其中包含所有迁移。要检查将其移动到其他位置,例如移动到/tmp文件夹,然后从那里运行:

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

    ./myapp run
    
  8. 结果

    您拥有单个文件,可用作迁移工具,也可用作工作应用程序。所有迁移都是建立的。在源代码中,它们存储在子包migrations中 - 因此很容易编辑。