<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          「GoCN酷Go推薦」sql 發(fā)布管理工具 gopg-migrations

          共 4759字,需瀏覽 10分鐘

           ·

          2021-10-25 21:22

          1. gopg-migrations 是什么?

          gopg-migrations 在我們使用數(shù)據(jù)庫時,每次發(fā)布都要改一些表結(jié)構(gòu),或者修改數(shù)據(jù)之類的操作。

          這些操作,手動執(zhí)行既危險,又容易忘記;當(dāng)新人看到奇怪的表結(jié)構(gòu),感覺到很詫異。如果我們能將所有操作管理起來,本地測試好之后再發(fā)布上去,那么就不會有上述這些問題。

          因此,gopg-migrations 這個庫,給我們帶來非常大的便利。當(dāng)然,這里是對 postgres 數(shù)據(jù)庫的支持。

          2. 怎么使用

          下載擴(kuò)展庫 github.com/go-pg/migrations/v7即可使用。

          2.1 假如我們先創(chuàng)建一個數(shù)據(jù)庫 students,然后調(diào)用 migrations 去執(zhí)行代碼。

          步驟如下:

          編寫創(chuàng)建表的 sql,使用 migrations 目錄管理起來,num_xxx 表示按照 num 順序執(zhí)行 主邏輯 main.go 主邏輯如下:

          package?main

          import?(
          ????"fmt"
          ????"time"

          ????pg?"github.com/test_go_pg/pg"

          ????"go.uber.org/zap"
          )

          func?main()?{
          ????fmt.Println("Starting?go-pg-migrations...")

          ????//?Bootstrap?check?pg
          ????if?err?:=?pg.PGDBWrite.Ping();?err?!=?nil?{
          ????????fmt.Println(pg.DBWriteConnectionError,?zap.Error(err))
          ????????return
          ????}
          ????fmt.Println("PostgreSQL?is?running",
          ????????zap.String("user",?pg.PGDBWrite.Options().User),
          ????????zap.String("addr",?pg.PGDBWrite.Options().Addr),
          ????????zap.String("db",?pg.PGDBWrite.Options().Database))

          ????//?Migrate?to?latest?pg?schema
          ????if?err?:=?pg.PGDBWrite.Migrate();?err?!=?nil?{
          ????????fmt.Println(pg.DBMigrationError,?zap.Error(err))
          ????????return
          ????}

          ????time.Sleep(time.Hour)
          ????fmt.Println("go-pg-migrations?is?stopping...")
          }

          gopg-migrations 相關(guān)函數(shù)編碼如下:

          package?pg

          import?(
          ????"context"
          ????"fmt"
          ????"time"

          ????"github.com/go-pg/migrations/v7"
          ????"github.com/go-pg/pg/v9"
          ????"go.uber.org/zap"
          )

          type?TGPGDB?struct?{
          ????*pg.DB
          }

          func?NewTGPGDB(db?*pg.DB)?*TGPGDB?{
          ????return?&TGPGDB{db}
          }

          type?TGPGDBOptions?struct?{
          ????Url?string

          ????DisableBeforeQueryLog?bool
          ????DisableAfterQueryLog??bool
          }

          func?CreateTGPGDB(url?string)?*TGPGDB?{
          ????return?CreateTGPGDBWithOptions(&TGPGDBOptions{Url:?url})
          }

          func?CreateTGPGDBWithOptions(dbOpts?*TGPGDBOptions)?*TGPGDB?{
          ????opts,?err?:=?pg.ParseURL(dbOpts.Url)
          ????if?err?!=?nil?{
          ????????fmt.Println(DBURLParseError,?zap.String("URL",?dbOpts.Url),?zap.Error(err))
          ????????return?nil
          ????}
          ????opts.ReadTimeout?=?DBReadTimeout
          ????opts.WriteTimeout?=?DBWriteTimeout
          ????opts.TLSConfig?=?nil?//?disabled?for?faster?local?connection?(even?in?production)
          ????if?DBNumConns?>?0?{
          ????????opts.PoolSize?=?DBNumConns
          ????}

          ????db?:=?NewTGPGDB(pg.Connect(opts))
          ????return?db
          }

          //?Ping?simulates?a?"blank?query"?behavior?similar?to?lib/pq's
          //?to?check?if?the?db?connection?is?alive.
          func?(db?*TGPGDB)?Ping()?error?{
          ????_,?err?:=?db.ExecOne("SELECT?1")
          ????return?err
          }

          //?Migrate?check?and?migrate?to?lastest?db?version.
          func?(db?*TGPGDB)?Migrate()?error?{
          ????//?Make?sure?to?only?search?specified?migrations?dir
          ????cl?:=?migrations.NewCollection()
          ????cl.DisableSQLAutodiscover(true)
          ????err?:=?cl.DiscoverSQLMigrations(DBMigrationsDir)
          ????if?err?!=?nil?{
          ????????return?err
          ????}

          ????var?oldVersion,?newVersion?int64
          ????//?Run?all?migrations?in?a?transaction?so?we?rollback?if?migrations?fail?anywhere
          ????err?=?db.RunInTransaction(func(tx?*pg.Tx)?error?{
          ????????//?Intentionally?ignore?harmless?errors?on?initializing?gopg_migrations
          ????????_,?_,?err?=?cl.Run(db,?"init")
          ????????//if?err?!=?nil?&&?!DBMigrationsAlreadyInit(err)?{
          ????????if?err?!=?nil{
          ????????????return?err
          ????????}
          ????????oldVersion,?newVersion,?err?=?cl.Run(db,?"up")
          ????????return?err
          ????})
          ????if?err?!=?nil?{
          ????????return?err
          ????}
          ????if?newVersion?==?oldVersion?{
          ????????fmt.Println("db?schema?up?to?date")
          ????}?else?{
          ????????fmt.Println("db?schema?migrated?successfully",?zap.Int64("from",?oldVersion),?zap.Int64("to",?newVersion))
          ????}
          ????return?nil
          }

          //?WithContextTimeout
          func?WithContextTimeout(ctx?context.Context,?f?func(ctx?context.Context))?{
          ????WithContextTimeoutValue(ctx,?DBStmtTimeout,?f)
          }

          //?WithContextTimeoutValue
          func?WithContextTimeoutValue(ctx?context.Context,?timeout?time.Duration,?f?func(ctx?context.Context))?{
          ????//?check?context?timeout?setting?with?upper?bound?read/write?limit
          ????if?timeout?>?DBReadTimeout?&&?timeout?>?DBWriteTimeout?{
          ????????fmt.Println(DBContextTimeoutExceedUpperBound,
          ????????????zap.Error(fmt.Errorf("query?timeout?%s?exceed?upper?bound?(%s|%s)",?timeout,?DBReadTimeout,?DBWriteTimeout)))
          ????}
          ????newCtx,?cancel?:=?context.WithTimeout(ctx,?timeout)
          ????f(newCtx)
          ????cancel()
          }

          直接運(yùn)行 go run main.go,此時代碼運(yùn)行,會生成 students 數(shù)據(jù)表:

          sql 如下:

          執(zhí)行后,會創(chuàng)建號數(shù)據(jù)表:students 和 gopg-migrations。

          查看 gopg-migrations 如下:

          2.2 假設(shè)我們要增加 sql 語句,怎么做呢?

          直接添加 sql 重新運(yùn)行 sql 如下:

          執(zhí)行如下:

          查看 students 數(shù)據(jù)表,發(fā)現(xiàn) 1,2 操作都已經(jīng)執(zhí)行了:

          2.3.管理 sql 語句

          類似 1,2 中的方式,我們可以添加更多的 sql 語句,把 sql 管理起來。

          總結(jié)

          gopg-migrations 這個庫,能夠把數(shù)據(jù)庫所有的操作 sql 全部管理起來,一方面可以讓我們清晰的看到 sql 項(xiàng)目的發(fā)展歷程,另一方面本地測試后發(fā)布更加安全!

          以上所有內(nèi)容均采用最新官方案例做示例

          參考資料

          查看全部代碼 (https://github.com/turingczz/test_go_pg)

          圖片上傳及查看,使用 swarm 網(wǎng)關(guān)實(shí)現(xiàn)(https://swarm-gateways.net/)


          《酷Go推薦》招募:


          各位Gopher同學(xué),最近我們社區(qū)打算推出一個類似GoCN每日新聞的新欄目《酷Go推薦》,主要是每周推薦一個庫或者好的項(xiàng)目,然后寫一點(diǎn)這個庫使用方法或者優(yōu)點(diǎn)之類的,這樣可以真正的幫助到大家能夠?qū)W習(xí)到

          新的庫,并且知道怎么用。


          大概規(guī)則和每日新聞類似,如果報(bào)名人多的話每個人一個月輪到一次,歡迎大家報(bào)名!戳「閱讀原文」,即可報(bào)名


          掃碼也可以加入 GoCN 的大家族喲~


          瀏覽 22
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  2024国产精品自拍 | 久久久久资源站 | 操逼.com | 蜜乳一区二区三区四区 | 三级视频国产 |