golangでトランザクション管理を少し楽にするラッパー関数
僕はgolang+mysqlを使っているのですが、いかんせんトランザクション管理に困っております。
go-sql-driver/mysql
にはbegin
、commit
、rollback
というメソッドがありますが
まさか一つ一つ手で書く・・・?
力技としてならそれもありかも・・・なんて思っていた時期がありました。
そしてトランザクション管理について調べていると、海外の方が良さげなラッパー関数を紹介してくれていました。
ラッパー関数
元記事はこちら↓
記事で紹介されているラッパー関数は下記になります。
func Transact(db *sql.DB, txFunc func(*sql.Tx) error) (err error) { tx, err := db.Begin() if err != nil { return } defer func() { if p := recover(); p != nil { tx.Rollback() panic(p) // re-throw panic after Rollback } else if err != nil { tx.Rollback() } else { err = tx.Commit() } }() err = txFunc(tx) return err }
これはすごい良いんじゃないでしょうか。
実際の処理は移譲していて、このラッパー関数の中ではbegin
でトランザクションを開始して
そのトランザクションを移譲する関数の引数に入れています。
そしてdefer
の中ではエラーがあればRollback
、無事に処理が終わればCommit
しています。
実際にラッパー関数を使用するときは
func (s Service) DoSomething() error { return Transact(s.db, func (tx *sql.Tx) error { if _, err := tx.Exec(...); err != nil { return err } if _, err := tx.Exec(...); err != nil { return err } }) }
上記のように、ラッパー関数の中に処理を書くことで使用できます。
この方法ならトランザクションをはりたい処理はラッパー関数の中に全部書くことができますね。
僕の中で現状のベストプラクティスになりそうです。
まとめ
golangでのトランザクション管理ってみんなどうしているんでしょうか。。
もしもgolangでゲームなどを作る場合はトランザクション管理が必須だし。。
でもその割には検索しても有力な知見も出てこない感じがするし。。
おわり!!