gerpo¶
gerpo (Golang + Repository) is a generic repository pattern for Go with pluggable adapters and minimal reflection. It is not an ORM: no migrations, no relations between entities, no struct tags. The entire SQL behavior is described declaratively in the repository configuration.
One-line ideology
Schema and SQL live inside the repository configuration; columns are bound to struct fields via pointers — not strings, not tags.
Database support
gerpo currently targets PostgreSQL (and PG-compatible databases such as CockroachDB). The SQL fragments gerpo emits — placeholder format, LIKE type-casts, INSERT … RETURNING, window functions — assume PostgreSQL. MySQL, MS SQL Server, and older SQLite are not supported today. See TODO for the multi-dialect backlog.
Install¶
Minimum Go version is 1.24.
Quick start¶
package main
import (
"context"
"time"
"github.com/google/uuid"
"github.com/insei/gerpo"
"github.com/insei/gerpo/executor/adapters/pgx5"
"github.com/insei/gerpo/query"
"github.com/jackc/pgx/v5/pgxpool"
)
type User struct {
ID uuid.UUID
Name string
Email *string // nullable
Age int
CreatedAt time.Time
}
func main() {
pool, _ := pgxpool.New(context.Background(), "postgres://...")
repo, err := gerpo.New[User]().
Adapter(pgx5.NewPoolAdapter(pool)).
Table("users").
Columns(func(m *User, c *gerpo.ColumnBuilder[User]) {
c.Field(&m.ID).OmitOnUpdate()
c.Field(&m.Name)
c.Field(&m.Email)
c.Field(&m.Age)
c.Field(&m.CreatedAt).OmitOnUpdate()
}).
Build()
if err != nil {
panic(err)
}
ctx := context.Background()
// Insert
u := &User{ID: uuid.New(), Name: "Alice", Age: 30, CreatedAt: time.Now()}
_ = repo.Insert(ctx, u)
// Query
list, _ := repo.GetList(ctx, func(m *User, h query.GetListHelper[User]) {
h.Where().Field(&m.Age).GTE(18)
h.OrderBy().Field(&m.CreatedAt).DESC()
h.Page(1).Size(20)
})
_ = list
}
Full runnable sample lives in examples/todo-api/ — a CRUD REST service with PostgreSQL, goose migrations and docker-compose wiring. Additional end-to-end scenarios are in the integration tests.
What to read next¶
-
How gerpo compares to GORM, ent, bun, sqlc and sqlx — feature matrix, strengths, weaknesses, and when each tool is the better pick.
-
Copy-paste starting point: pgx v5 + goose migrations + OpenTelemetry tracer + request-scope cache + domain error mapping + transactions — all in one place.
-
examples/todo-api/— a CRUD REST service with PostgreSQL, goose migrations and docker-compose wiring.docker compose up --buildand you have a working tasks API. ~350 lines of Go in one place. -
A walkthrough of every repository capability: CRUD, filters, ordering, hooks, soft delete, virtual columns, cache, transactions, adapters.
-
Catch
EQ("18")on anintfield atgo vettime. Ships as a standalone binary and as a golangci-lint v2 plugin. -
How gerpo is built internally: layers, SQL generation, pointer-based field mapping via fmap, adapter implementations, Cache. For contributors.
-
Autogenerated on pkg.go.dev — including runnable examples next to every method.
-
Source, issue tracker, pull requests.
Supported adapters¶
gerpo talks to a database through an executor.Adapter — a thin wrapper around an underlying SQL driver. gerpo targets PostgreSQL today; all three bundled adapters wrap PostgreSQL drivers:
| Adapter | Package | Wraps driver | Placeholder format |
|---|---|---|---|
| pgx v5 | executor/adapters/pgx5 |
github.com/jackc/pgx/v5 |
$1, $2, … |
| pgx v4 | executor/adapters/pgx4 |
github.com/jackc/pgx/v4 |
$1, $2, … |
| database/sql | executor/adapters/databasesql |
any database/sql driver — pair with a PG driver (pq, pgx/stdlib) |
? or $1 (configurable) |
PG-compatible databases (CockroachDB, MariaDB ≥10.5, SQLite ≥3.35) are likely to work drop-in but are not formally tested. MySQL, MS SQL Server, and older SQLite are not supported — the SQL gerpo emits (LIKE CAST(? AS text), INSERT … RETURNING, COUNT(*) OVER ()) assumes PostgreSQL. See the TODO file for the multi-dialect backlog.
You can wrap a custom adapter — implement executor.Adapter (ExecContext, QueryContext, BeginTx). See Adapters.