dongqin1819 2017-10-31 07:44
浏览 88
已采纳

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

I have a Golang 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.

Is there an equivalent in Golang to accomplish that?

  • 写回答

3条回答 默认 最新

  • dpl9717 2017-11-01 07:26
    关注

    How to get a single file which can migrate database and work

    1. Install

      go get -u github.com/pressly/goose/cmd/goose
      
    2. 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
      ")  //
             ..... 
             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
      ", driver)
          }
      
          switch dbstring {
          case "":
              log.Fatalf("-dbstring=%q not supported
      ", dbstring)
          default:
          }
      
          if driver == "redshift" {
              driver = "postgres"
          }
      
          db, err := sql.Open(driver, dbstring)
          if err != nil {
              log.Fatalf("-dbstring=%q: %v
      ", 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. Create folder for migrations:

      mkdir migrations && cd migrations
      
    4. Create first migrations. We will use go-style migrations:

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

      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.

    5. Then go to the main folder and build the application:

      cd ..
      go build -v -o myapp *.go
      
    6. 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
      
    7. Run your app:

      ./myapp run
      

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥30 Matlab打开默认名称带有/的光谱数据
  • ¥50 easyExcel模板 动态单元格合并列
  • ¥15 res.rows如何取值使用
  • ¥15 在odoo17开发环境中,怎么实现库存管理系统,或独立模块设计与AGV小车对接?开发方面应如何设计和开发?请详细解释MES或WMS在与AGV小车对接时需完成的设计和开发
  • ¥15 CSP算法实现EEG特征提取,哪一步错了?
  • ¥15 游戏盾如何溯源服务器真实ip?需要30个字。后面的字是凑数的
  • ¥15 vue3前端取消收藏的不会引用collectId
  • ¥15 delphi7 HMAC_SHA256方式加密
  • ¥15 关于#qt#的问题:我想实现qcustomplot完成坐标轴
  • ¥15 下列c语言代码为何输出了多余的空格