// Created on savesnippets.com ยท https://savesnippets.com/zu1q8TU09fkulY package main import ( "context" "database/sql" ) func WithTx(ctx context.Context, db *sql.DB, fn func(*sql.Tx) error) (err error) { tx, err := db.BeginTx(ctx, nil) if err != nil { return err } defer func() { if p := recover(); p != nil { _ = tx.Rollback() panic(p) // re-panic after rollback } else if err != nil { _ = tx.Rollback() } else { err = tx.Commit() } }() return fn(tx) } // Usage // // err := WithTx(ctx, db, func(tx *sql.Tx) error { // if _, err := tx.ExecContext(ctx, "INSERT INTO orders ..."); err != nil { // return err // auto-rollback // } // _, err := tx.ExecContext(ctx, "UPDATE inventory SET qty = qty - 1 WHERE id = ?", 42) // return err // })