Паттерн: defer tx.Rollback() сразу после Begin(). После успешного tx.Commit() вызов Rollback() ничего не делает (возвращает sql.ErrTxDone). Так откат гарантирован при любой ошибке или panic до Commit.
tx, err := db.Begin()
if err != nil { return err }
defer tx.Rollback()
if _, err = tx.Exec(...); err != nil { return err }
if _, err = tx.Exec(...); err != nil { return err }
return tx.Commit() // после Commit defer Rollback не делает откат