GORM Gen: Type-Safe DAO Code Generation for GORM Projects
Gen: Friendly & Safer GORM powered by Code Generation
At a glance
- What is it?
- GORM Gen generates typed query APIs and DAO methods from your database schema, trading runtime reflection for compile-time safety. This review covers its generation modes, template syntax, and where it fits, with a clear look at its limitations.
- Who is it for?
- Adopt GORM Gen if you are already on GORM, want to eliminate stringly-typed queries, and can commit to a code generation step in your build. Skip it if you prefer runtime flexibility, need to generate code from dynamic schemas, or dislike the extra files and re-generation workflow.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 24 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.
Star history
- go-gorm/gen2,560 ★ · +2
| Repository | 2026-08-27 | 2026-11-13 |
|---|---|---|
| go-gorm/gen | 2.6k | 2.6k |
2 Stars in the last 78 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
The Problem: GORM's Stringly-Typed Queries
GORM, the popular Go ORM, lets you write queries like `db.Where("age > ?", 18).Find(&users)`. The column name and condition are strings, so a typo in `age` or `name` only surfaces at runtime, often in production. GORM Gen addresses this by generating code from your database schema. The generated code exposes typed fields, like `u.Age.Gt(18)`, where `Age` is a struct field and `Gt` is a method. The compiler catches mistakes before you run the program. This is a specific solution for teams that want the convenience of an ORM without sacrificing type safety. It targets Go developers already using GORM, because it builds on GORM's own dialectors and plugins. The README states it generates "idiomatic, reusable DAO APIs" from schema and interface templates. That is the core promise: static typing for database access.
How Generation Works: Schema to Structs to Query API
The mechanism is a two-step process. First, you write a small Go program, typically in `cmd/gen/main.go`, that opens a database connection and calls `gen.NewGenerator`. You pass a config with an output path, like `internal/dal/query`, and mode flags. Then you call `g.UseDB(db)` and `g.ApplyBasic(g.GenerateAllTable()...)`. The generator reads the database schema and creates model structs and a query package. The generated query API uses GORM's underlying methods, so you still use the same plugins and dialectors. The README shows two usage patterns. With `WithDefaultQuery`, you call `query.SetDefault(db)` once at startup, then use `query.User` directly. Without it, you create a query handle with `query.Use(db)` and pass it around. The second pattern avoids a global variable, which is cleaner for testing. The generated code is not a runtime ORM; it is a compile-time wrapper. That is why the README calls it "powered by Code Generation."
Getting Started: Commands and Config Keys
Installation is a standard Go module fetch: `go get gorm.io/gen@latest`. The generation entry point is a Go file you check in, not a separate binary. The README recommends `cmd/gen/main.go`. A minimal generator opens a MySQL connection via `gorm.Open`, creates a `gen.NewGenerator` with `OutPath` and `Mode`, then runs `g.Execute()`. You run it with `go run ./cmd/gen`. The `Mode` flags control the API shape. `WithDefaultQuery` enables the global `SetDefault` pattern. `WithQueryInterface` is needed for interface-based SQL methods. `WithGeneric` switches to a generics-based query API. `WithoutContext` removes the context parameter. There is also `Config.UseAny`, which makes generated code emit `any` instead of `interface{}`, but it requires Go 1.18 or later and rewrites `interface{}` even in comments. The README calls this an "opt-in" feature. For field tags, you can enable `FieldNullable`, `FieldCoverable`, and `FieldWithIndexTag` to get more detailed struct tags. These are the main knobs, and the README is clear that there is one generator entry point.
Interface SQL Templates: A Second Way to Generate Methods
Beyond schema generation, Gen lets you define custom query methods using a Go interface with SQL comments. You write a method signature and put the SQL in a comment above it. For example, `FindByID(id int) gen.T` with a comment containing `SELECT * FROM users WHERE id=@id`. The generator parses that comment and produces a typed method on the generated model. The template syntax includes `{{where}}` and `{{if}}` blocks for dynamic conditions. The README shows a `FindByOptionalName` method that only adds a `name=` condition when the parameter is not empty. This is a powerful feature for building reusable query methods without writing raw SQL strings in your business logic. However, the documentation is thin. The README says the template syntax reference exists in the test corpus, specifically `tests/diy_method/method.go`. That is a signal that the template language is not fully documented in the README. You would need to read test files to learn the full syntax. That is a real friction point for adoption.
Generics Mode and Code Style Options
The generics mode, enabled by `WithGeneric`, changes the generated query API to use Go generics for stronger typing. The README explicitly says generics is not a separate workflow; it just alters the API surface. This means the same schema generation produces a different query interface. The benefit is more type safety, but it also means the generated code requires Go 1.18 or later. The `UseAny` option is similar in that it targets newer Go versions. These options are opt-in, so you can start with the default non-generic mode and migrate later. The README does not give examples of the generic API, so you would need to inspect generated code or run examples. That is a gap. The project's own examples directory is mentioned, but not detailed. For a library that promises safety, the lack of explicit generic examples in the README is a weakness.
Limitations and Wrong-Tool Cases
Gen is not the right tool if your database schema changes frequently. Every schema change requires re-running the generator and committing new files. That is a workflow change, not a one-time setup. If you have a dynamic schema, such as a multi-tenant system with per-tenant tables, generation becomes a build-time bottleneck. Also, the interface template syntax is not fully documented in the README. The project points to test files for reference, which is unusual for a production library. You may spend time reverse-engineering the template language. Another limitation: Gen is tied to GORM. If you are not using GORM, this library has no value. Even within GORM, the generated code is a wrapper, so you are still bound by GORM's behavior and its own limitations. The README does not mention any performance overhead, but code generation adds build time and repository size. For small projects with a handful of tables, the setup cost may outweigh the benefit.
Alternative Approaches: sqlc and Manual Structs
A direct alternative is `sqlc`, which also generates Go code from SQL, but with a different approach. `sqlc` takes raw SQL queries (in `.sql` files) and generates type-safe Go functions for each query. It does not require a database connection at generation time; you write the SQL, and it parses it. Gen, by contrast, requires a live database to read the schema, and it generates the query API from the schema, not from your hand-written SQL. For interface templates, you write SQL in comments, but the core generation is schema-driven. `sqlc` is more focused on query generation, while Gen is a full DAO generator that also produces model structs. Another alternative is to write your own structs and use GORM's `Where` with string conditions, but that loses type safety. The choice depends on whether you want to define queries as SQL first (`sqlc`) or let the schema drive everything (Gen). Gen is closer to GORM, so it integrates more naturally with existing GORM plugins.
Maintenance, Upgrades, and License
The project is under active maintenance. The repository shows recent releases in 2026, with v0.3.29 and a separate `gentool` release. The license is MIT, which permits commercial use, modification, and distribution with attribution. There is no mention of a migration guide between versions, so upgrading may require regenerating code and checking for API changes. The generated code is committed to your repository, so you must track changes when you upgrade Gen. The README recommends a project layout with `cmd/gen/main.go` checked in, which makes generation reproducible. That is good for CI, but it also means your build depends on the generator version. The maintenance cost is mainly the re-generation step and the need to keep the generator config in sync with schema changes. The project has multiple maintainers, including the GORM author, which adds credibility, but the README does not document a deprecation policy or versioning strategy. You should pin the Gen version and test generated code after upgrades.
Editorial conclusion
Adopt GORM Gen if you are already on GORM, want to eliminate stringly-typed queries, and can commit to a code generation step in your build. Skip it if you prefer runtime flexibility, need to generate code from dynamic schemas, or dislike the extra files and re-generation workflow. Before adopting, verify that your GORM version matches the generated code's expectations, test the template syntax with your own SQL, and confirm that the generated query API covers the joins and subqueries you need. The project is under active maintenance, with recent releases in 2026, but the interface template syntax is documented mainly through test files, so budget time for trial and error.
Frequently asked questions
How do I install GORM Gen?
As a library, with go get gorm.io/gen@latest. The module is gorm.io/gen and its go.mod requires Go 1.22.0, depending on gorm.io/gorm v1.31.2, gorm.io/hints, gorm.io/datatypes and gorm.io/plugin/dbresolver among others.
What is the difference between WithDefaultQuery and query.Use(db)?
WithDefaultQuery lets the generated package hold a default connection, set once with query.SetDefault(db) at startup, after which tables are reached as query.Table with no handle passed. Without that flag you build a handle with q := query.Use(db) and pass the connection where the query is built, keeping it visible and out of package level state.
Where is the SQL template syntax for interface methods documented?
The README points at the test corpus, tests/diy_method/method.go, as the syntax reference. The example interface uses @id style parameters with {{where}}, {{if name != ""}} and {{end}} directives, and is bound with g.ApplyInterface alongside g.GenerateModel("users").
What does Config.UseAny change in generated code?
It emits any instead of interface{} in generated code. It is opt-in, the target module needs Go 1.18 or newer, and it also rewrites the literal text interface{} inside comments and string literals, so it touches text as well as code.
Is there a command line tool instead of writing a generator program?
Yes, GenTool, documented at tools/gentool/README.md with a Simplified Chinese README beside it. It is released as its own module, tools/gentool v0.0.3, published on the same day as v0.3.29 of the library.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/go-gorm-gen)Star history chart for your README
[](https://hysenlabs.com/projects/go-gorm-gen)Was this useful?