Gen: Friendly & Safer GORM powered by Code Generation
GORM Gen
Friendly & Safer GORM powered by Code Generation.
Overview
- Generate idiomatic, reusable DAO APIs from database schema and/or interface-based SQL templates
- Type-safe query DSL (fields, conditions, assignments) with strong static typing (including generics mode)
- Database-to-struct follows GORM conventions (tags, nullable/default/unsigned/index/type, etc.)
- Built on top of GORM: use the same plugins, dialectors, and ecosystem you already have
Documentation
- Gen Guides (official site): https://gorm.io/gen/index.html
- GORM Guides: https://gorm.io/docs
Quick Start
Install as a library:
go get gorm.io/gen@latest
1) Generate code
Create a generator entry (recommended: cmd/gen/main.go):
package main
import ( "gorm.io/driver/mysql" "gorm.io/gen" "gorm.io/gorm" )
func main() { db, err := gorm.Open(mysql.Open("dsn"), &gorm.Config{}) if err != nil { panic(err) }
g := gen.NewGenerator(gen.Config{ OutPath: "internal/dal/query", Mode: gen.WithDefaultQuery | gen.WithQueryInterface, // enable query.SetDefault(db) })
g.UseDB(db) g.ApplyBasic(g.GenerateAllTable()...) g.Execute() }
Run generation:
go run ./cmd/gen
2) Use generated code
If you enabled WithDefaultQuery, initialize once at startup:
package main
import ( "context"
"gorm.io/driver/mysql" "gorm.io/gorm"
"your/module/internal/dal/query" )
func main() { db, err := gorm.Open(mysql.Open("dsn"), &gorm.Config{}) if err != nil { panic(err) }
query.SetDefault(db)
u := query.User , = u.WithContext(context.Background()). Where(u.Age.Gt(18)). Find() }
query.SetDefault(db) only needs to run once (e.g. during service startup). After that, use query.<Table> directly.
If you don’t want a global default, skip WithDefaultQuery and use:
q := query.Use(db)
, = q.User.WithContext(ctx).Where(q.User.Age.Gt(18)).Find()
More runnable examples: examples
Common Setups
Gen has one generator entry point (gen.NewGenerator(gen.Config{...})). The main knobs you typically use are:
- What to generate: DB schema → models/query; plus optional interface-SQL methods
- How the query API looks:
Config.Modeflags (WithDefaultQuery,WithoutContext,WithQueryInterface,WithGeneric)
Setup A: DB schema → model + query (recommended baseline)
g := gen.NewGenerator(gen.Config{
OutPath: "internal/dal/query",
Mode: gen.WithDefaultQuery | gen.WithQueryInterface,
FieldNullable: true, FieldCoverable: true, FieldWithIndexTag: true, }) g.UseDB(db) g.ApplyBasic(g.GenerateAllTable()...) g.Execute()
Setup B: Interface SQL templates → reusable typed methods
Define an interface with SQL comments/templates:
package dal
import "gorm.io/gen"
type UserMethods interface { // FindByID // // SELECT * FROM users WHERE id=@id FindByID(id int) gen.T
// FindByOptionalName // // SELECT * FROM users // {{where}} // {{if name != ""}} // name=@name // {{end}} // {{end}} FindByOptionalName(name string) []gen.T }
Bind the interface to a generated model/table:
g.ApplyInterface(func(m UserMethods) {}, g.GenerateModel("users"))
Template syntax reference exists in the test corpus: method.go.
Setup C: Generics query API
Generics is not a separate “workflow”; it changes the generated query API surface for stronger typing.
g := gen.NewGenerator(gen.Config{
OutPath: "internal/dal/query",
Mode: gen.WithDefaultQuery | gen.WithGeneric,
})
Recommended Project Layout
Keep code generation isolated and reproducible (works well with go:generate and CI).
your-repo/
internal/
dal/
model/ # generated model structs (optional)
query/ # generated query (+ DIY methods)
cmd/
gen/
main.go # generator entry (checked in)
CLI Tool
If you prefer a CLI workflow, use GenTool:
Maintainers
@riverchu @iDer @qqxhb @dino-ma
Contributing
You can help to deliver a better GORM/Gen, check out things you can do
License
Released under the MIT License