gormdb2struct is a schema-first code generator for Go + GORM that emits typed gorm.io/gen query code.
It connects to an existing PostgreSQL or SQLite database and generates:
- GORM model structs
- typed
gorm.io/genquery helpers - an optional
DbInitfile for the chosen dialect - optional PostgreSQL wrapper types for enums, domains, and enum arrays
If your database schema is the source of truth and you are tired of hand-maintaining structs, gorm.io/gen query scaffolding, and custom type plumbing, this tool is built for that workflow.
Many Go teams using GORM still end up doing a lot of repetitive work by hand:
- rebuilding model structs every time the schema changes
- writing boilerplate around PostgreSQL enums and domains
- keeping generated query code and manual model code in sync
- stitching database-specific initialization code into each project
gormdb2struct exists to take that work off the critical path without introducing hidden state or a heavyweight framework.
This tool is a strong fit if you:
- already have a PostgreSQL or SQLite schema
- use GORM and want typed query helpers from
gorm.io/gen - want a config-first CLI that works well in CI/CD
- have PostgreSQL enums, domains, arrays, or custom wrapper types that need to stay honest
It is especially useful for PostgreSQL-heavy codebases where enums and domains are part of the real application contract, not just database decoration.
- PostgreSQL and SQLite support today
- Typed query generation via
gorm.io/gen - Versioned, human-editable TOML configuration
- Optional
DbInitgeneration with app-settings andslog-gormsupport - Unified
TypeMapfor standard types, enums, domains, and arrays - PostgreSQL generated wrapper types for enums, domains, and enum arrays
- PostgreSQL inspection commands that recommend missing mappings and can emit a starter config
- Support for importing existing Go type packages so the inspector can recommend real
TypeMapentries instead of generated wrappers - Built-in
pgtypespackage for PostgreSQL arrays and intervals - Stateless CLI design with no persistent local settings
brew tap dan-sherwin/homebrew-tap
brew install gormdb2structOr:
brew install dan-sherwin/homebrew-tap/gormdb2structDownload the latest archive from the Releases page, extract it, and place gormdb2struct somewhere on your PATH.
sudo dnf config-manager --add-repo https://dan-sherwin.github.io/dan-sherwin.repo
sudo dnf install gormdb2structOn older yum-based systems, install the repo-management package first if needed.
Requires Go 1.26+.
git clone https://github.com/dan-sherwin/gormdb2struct.git
cd gormdb2struct
go build -o gormdb2struct ./cmd
./gormdb2struct --helpGenerate a starter config:
gormdb2struct generate-config-sampleIf you are working against PostgreSQL and want help discovering enums, domains, and custom types before you write a config by hand:
gormdb2struct inspect-postgresql \
--host localhost \
--database my_database \
--user my_user \
--password-env DB_PASSWORD \
-o starter.tomlIf you already know you want to reuse types from an existing Go package, include it:
gormdb2struct inspect-postgresql \
--host localhost \
--database my_database \
--user my_user \
--password-env DB_PASSWORD \
--import-package go.corp.spacelink.com/sdks/go/sl_datatypes \
-o starter.tomlThen generate the code:
gormdb2struct ./starter.tomlFor a full self-contained walkthrough you can run locally, see examples/sqlite-quickstart.
If you already have a config and just want a recommendation pass over the objects it references:
gormdb2struct inspect ./gormdb2struct.tomlFor a paste-ready TOML recommendation snippet from an existing config:
gormdb2struct inspect ./gormdb2struct.toml --format tomlThe differentiator is not just model generation. It is the PostgreSQL type story.
gormdb2struct can help with cases like:
- PostgreSQL enums that should become real Go enum wrapper types
- PostgreSQL domains that should map to existing application types
- enum arrays that need a real wrapper type instead of a raw slice
- projects that already have packages like
sl_datatypesand want those reused automatically in generated config recommendations
That means you can mix and match:
- generated wrappers for schema-defined enums and domains
- explicit
TypeMapentries for hand-written domain types you already trust - default built-in support from
pgtypesfor common PostgreSQL arrays and intervals
gormdb2struct supports four main entry points:
gormdb2struct <config.toml>Generate code from a config file.gormdb2struct generate-config-sampleWrite a full commented starter config.gormdb2struct inspect <config.toml>Inspect the PostgreSQL objects referenced by an existing config and recommend type mappings.gormdb2struct inspect-postgresqlConnect directly to PostgreSQL from CLI flags, print an inspection report, and optionally emit a starter config.
inspect-postgresql password input options:
--password--password-env--password-stdin--password-prompt
If -o/--out is omitted, inspect-postgresql prints only the human-readable inspection report.
If -o stdout is used, it prints the starter TOML after the report.
If -o <path> is used, it writes only the starter TOML to that file.
The preferred config format is explicit and versioned:
ConfigVersion = 1If ConfigVersion is omitted, gormdb2struct falls back to a legacy compatibility parser for older shipped configs.
Main sections in the versioned format:
[Generator][Database][Database.PostgreSQL][Database.SQLite][DbInit][TypeMap][ExtraFields][JSONTagOverridesByTable][PostgreSQL.GeneratedTypes][PostgreSQL.GeneratedTypes.TypeMap]
Use gormdb2struct generate-config-sample for the full commented example. The sample is structured for hand editing and grouped so dialect-specific settings are easy to find.
Minimal PostgreSQL example:
ConfigVersion = 1
[Generator]
OutPath = "./generated"
Objects = ["tickets", "ticket_extended"]
ImportPackagePaths = ["github.com/dan-sherwin/gormdb2struct/pgtypes"]
[Database]
Dialect = "postgresql"
[Database.PostgreSQL]
Host = "localhost"
Port = 5432
Name = "ticket_data_core"
User = "ticket_service"
Password = "secret"
SSLMode = false
[DbInit]
Enabled = true
IncludeAutoMigrate = false
[TypeMap]
"spacelink_identifier" = "sl_datatypes.SpacelinkIdentifier"
[PostgreSQL.GeneratedTypes]
PackageName = "types"
RelativePath = "models/types"
[PostgreSQL.GeneratedTypes.TypeMap]
"ticket_status" = "TicketStatus"
"ticket_type" = "TicketType"Validation highlights:
[Generator].OutPathis required[Database].Dialectmust bepostgresqlorsqlite- PostgreSQL requires host and database name
- SQLite requires a database file path
- PostgreSQL generated types are only available when the dialect is PostgreSQL
Given OutPath = "./generated":
./generated/modelsGenerated model structs withgormandjsontags./generatedgorm.io/genquery helpers and optionaldb.go/db_sqlite.go./generated/models/dbtypesor your configured generated-types path PostgreSQL wrapper types whenPostgreSQL.GeneratedTypesis enabled
If OutPackagePath is omitted, gormdb2struct will try to derive it from the current Go module when it needs to emit importable generated files like DbInit.
DbInit generation is optional and controlled by the [DbInit] section.
When enabled, generated init code can:
- open the database connection for the selected dialect
- register default query objects
- optionally run
AutoMigrate - optionally register database settings with
github.com/dan-sherwin/go-app-settings - optionally use
github.com/orandin/slog-gormas the GORM logger
DbInit returns an error instead of panicking or exiting, so the parent application stays in control.
The repo also ships a reusable pgtypes package for PostgreSQL array and interval handling.
It includes support for types like:
pgtypes.StringArraypgtypes.BoolArraypgtypes.Int32Arraypgtypes.Int64Arraypgtypes.Float64Arraypgtypes.UUIDArraypgtypes.TimeArraypgtypes.Durationpgtypes.DurationArray
This package is useful even outside the generator if you want GORM-friendly wrappers for PostgreSQL array and interval columns.
cmd/main.goSingle executable entrypointcmd/appCLI parsing, top-level command dispatch, logging, and version/build metadatainternal/configConfig loading, normalization, validation, and sample generationinternal/generatorSchema inspection, generation orchestration, dialect handling, and emitted-file logicpgtypesPublic PostgreSQL helper types for generated projects
The tool is intentionally stateless. There are no persistent settings and no hidden local project database.
The local quality gate lives at:
./dev/ci-local.shThat script runs formatting checks, build, vet, tests, lint, and govulncheck.
Current support is focused on PostgreSQL and SQLite.
Additional GORM dialects are planned for future releases, with likely expansion in this order:
- MySQL
- TiDB
- GaussDB
- SQL Server
- ClickHouse
- Oracle
The long-term goal is not just more dialectors, but dialect-specific generation that stays honest about what each database can actually support.
Issues and pull requests are welcome. Clear reproduction steps, config samples, and tests are especially helpful.
This project is licensed under the terms of the LICENSE file in this repository.