package store
import (
"context"
"database/sql"
)
type Querier interface {
WithTx(tx *sql.Tx) Querier
// ... add the methods you actually use
}
func InTx(ctx context.Context, db *sql.DB, q Querier, fn func(context.Context, Querier) error) error {
tx, err := db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelReadCommitted})
if err != nil {
return err
}
defer tx.Rollback()
if err := fn(ctx, q.WithTx(tx)); err != nil {
return err
}
return tx.Commit()
}
When using sqlc, the generated query set usually has a WithTx method. I wrap that pattern so business logic can depend on an interface and still run inside a transaction. The key is to keep transaction boundaries explicit while avoiding passing *sql.Tx everywhere. The helper below begins a transaction, creates a transaction-bound querier via WithTx, runs the function, and commits on success. defer tx.Rollback() is the boring safety net that prevents leaked transactions on early returns. In production, I also set an isolation level via sql.TxOptions and I ensure ctx has a deadline so transactions don’t sit open. This is a small abstraction, but it keeps service methods tidy and makes unit testing easier because you can mock the interface.
Related snips
package api
import (
"net/http"
"runtime/debug"
)
Expose build metadata for debugging deploys
package dbutil
import (
"context"
"github.com/jackc/pgconn"
Retry Postgres serialization failures with bounded attempts
require "csv"
class PeopleCsvStream
include Enumerable
HEADERS = %w[id full_name email signed_up_at plan].freeze
Resilient CSV Export as a Streamed Response
class SignupForm
include ActiveModel::Model
include ActiveModel::Attributes
attribute :account_name, :string
attribute :email, :string
Shallow Controller, Deep Params: Form Object Pattern
# BAD: N+1 query problem
@users = User.all
@users.each do |user|
puts user.posts.count # Fires query for each user!
end
ActiveRecord query optimization and N+1 prevention
class AddSettingsToAccounts < ActiveRecord::Migration[7.1]
disable_ddl_transaction!
def change
add_column :accounts, :settings, :jsonb, null: false, default: {}
Postgres JSONB Partial Index for Feature Flags
Share this code
Here's the card — post it anywhere.