Friendly & Safer GORM powered by Code Generation.
- 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
- Gen Guides (official site): https://gorm.io/gen/index.html
- GORM Guides: https://gorm.io/docs
Install as a library:
go get gorm.io/gen@latestCreate 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/genIf 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
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)
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()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.
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,
})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)
If you prefer a CLI workflow, use GenTool:
@riverchu @iDer @qqxhb @dino-ma
You can help to deliver a better GORM/Gen, check out things you can do
Released under the MIT License