Storage-agnostic logic
Write business code against dal.Database. Decide later whether it lives in Postgres, Firestore, or a JSON file on disk.
DALgo is a Database Abstraction Layer for Go. Write your domain logic once against a single, well-tested interface — swap Postgres for Firestore, SQLite for Datastore, an in-memory store for a real one — without touching your business code.
Six reasons developers reach for DALgo on day one.
Write business code against dal.Database. Decide later whether it lives in Postgres, Firestore, or a JSON file on disk.
One small, opinionated API replaces piles of driver-specific boilerplate. Records, keys, queries, transactions — uniform across every adapter.
Swap a production driver for an in-memory one in tests. No mocks-of-mocks. mocks4dalgo ships generated mocks for the whole interface surface.
Because every operation goes through one interface, observability and audit logging are a wrapper — not a refactor.
Every official adapter is validated against the same end-to-end test suite. Conformance is the contract.
Read-only and read-write transactions are first-class. Pass a closure, get atomicity — without leaking driver-specific transaction types into your domain.
Ten official adapters spanning SQL, NoSQL, embedded key-value, file, and Git-versioned storage.
The interface itself. dal, orm, record, update, transactions, errors.
Adapter for the standard database/sql — Postgres, MySQL, MSSQL, anything compliant.
SQLite-specific driver: schema, DDL, concurrency-aware operations on top of dalgo2sql.
For Google Cloud Firestore — a globally distributed NoSQL document database.
github.com/dal-go/dalgo2firestoreFor Google Cloud Datastore — Firestore's predecessor, still widely deployed on App Engine.
github.com/dal-go/dalgo2datastoreFor BuntDB — an embeddable in-memory key/value store with custom indexing and geospatial support.
github.com/dal-go/dalgo2buntdbFor BadgerDB — an embeddable, persistent, fast key-value database written in pure Go.
github.com/dal-go/dalgo2badgerPersist data on the local filesystem in human-readable formats — JSON, YAML, CSV.
github.com/dal-go/dalgo2filesVersioned, auditable storage backed by a Git repository — every write is a commit.
github.com/dal-go/dalgo2gitAdapter for inGitDB — a Git-native database with branchable, mergeable data. Lives in the inGitDB CLI.
github.com/ingitdb/ingitdb-cliA working example in fewer than 40 lines.
Install the core module and one adapter — say, SQLite for local development.
Open a database. The returned dal.Database is the only type your app needs to know about.
Define a record, set its data, persist it inside a read-write transaction.
Later, swap dalgo2sqlite for dalgo2firestore. Your handlers don't change.
// $ go get github.com/dal-go/dalgo
// $ go get github.com/dal-go/dalgo2sqlite
package main
import (
"context"
"log"
"github.com/dal-go/dalgo/dal"
"github.com/dal-go/dalgo2sqlite"
)
type User struct {
Name string `json:"name"`
Email string `json:"email"`
}
func main() {
ctx := context.Background()
db, err := sqlite.Open(ctx, "app.db")
if err != nil {
log.Fatal(err)
}
user := &User{Name: "Ada", Email: "ada@example.com"}
key := dal.NewKeyWithID("users", "u_001")
rec := dal.NewRecordWithData(key, user)
err = db.RunReadwriteTransaction(ctx,
func(ctx context.Context, tx dal.ReadwriteTransaction) error {
return tx.Insert(ctx, rec)
},
)
if err != nil {
log.Fatal(err)
}
}
Strict enough to keep every adapter honest.
Every DALgo adapter — SQL, NoSQL, embedded, filesystem — implements the same
dal.Database contract. Read operations live on
ReadonlySession; mutating operations live on
ReadwriteSession. Transactions are closures: pass a function, the
driver gives you a session, your code never sees a driver-specific handle.
dalgo.ErrNotSupported — explicit failure beats silent nonsense.package dal
type Database interface {
TransactionCoordinator
ReadonlySession
}
type TransactionCoordinator interface {
RunReadonlyTransaction(ctx context.Context,
f ROTxWorker, opts ...TransactionOption) error
RunReadwriteTransaction(ctx context.Context,
f RWTxWorker, opts ...TransactionOption) error
}
type ReadonlySession interface {
Get(ctx context.Context, record Record) error
GetMulti(ctx context.Context, records []Record) error
Select(ctx context.Context, query Select) (Reader, error)
}
type ReadwriteSession interface {
ReadonlySession
Insert(ctx context.Context, r Record, opts ...InsertOption) error
Set(ctx context.Context, r Record) error
Update(ctx context.Context, key *Key,
updates []Update, pre ...Precondition) error
Delete(ctx context.Context, key *Key) error
}
DALgo is MIT-licensed, production-tested, and waiting for you to break it. Contributions for new adapters and edge cases are welcome.