如何将迁移与可执行文件绑定 [英] How to bind migrations with executable

查看:107
本文介绍了如何将迁移与可执行文件绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a Go project using goose for Mysql migrations. I would like to bind the migrations to the package executable so that the executable can be deployed and used independently from any system, similar to JAR files in JAVA projects.

Go中是否有等效的工具来实现这一目标?

Is there an equivalent in Go to accomplish that?

推荐答案

如何获取可以迁移数据库并正常工作的单个文件

  1. 安装

  1. Install

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

  • 制作应用.我基于example main.go并添加run选项.假设您的项目位于github.com/user/project:

  • Make app. I base it on examplemain.go and add run option. Suppose your project is located at 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
    `
    )
    

  • 为迁移创建文件夹:

  • Create folder for migrations:

    mkdir migrations && cd migrations
    

  • 创建第一个迁移.我们将使用go样式的迁移:

  • Create first migrations. We will use go-style migrations:

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

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

    You'll get a file 00001_init.go with Go code. Migrations are baked in it as SQL-commands. Just edit them as you need.

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

    Then go to the main folder and build the application:

    cd ..
    go build -v -o myapp *.go
    

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

  • You'll get a file myapp with all the migrations baked in it. To check move it to some other place, for example to /tmp folder, and run from there:

    ./myapp mysql "user:password@/dbname?parseTime=true" status
    

  • 运行您的应用程序:

  • Run your app:

    ./myapp run
    

  • 结果

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

    Result

    You have single file which can be used as a migration tool so as a working application itself. All the migration are buil-it. In source code they are stored in a subpackage migrations - so it's easy to edit.

    这篇关于如何将迁移与可执行文件绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆