GORM From Zero
Most Go web services that talk to a SQL database talk to it through GORM. It's the de-facto ORM for Go: you define your tables as plain structs, and GORM handles the SQL for create, read, update, delete, relationships, and migrations. If you've used an ORM in another language, GORM will feel familiar; if you haven't, it's the gentlest way into "describe your data as Go types, let the library write the SQL." And because Go developers value knowing what's really happening, the most useful thing about learning GORM is seeing exactly which SQL each call produces — so you can drop to raw SQL the moment the ORM gets in your way.
The mental model is three pieces. A model is a Go struct that maps to a table (often embedding
gorm.Model for ID/timestamps/soft-delete). The *gorm.DB value is your handle to the database
and the thing you chain methods on (db.Where(...).Order(...).Find(...)). And a session/chain is how
those calls build one query. Hold "struct = table, *gorm.DB = the query builder you chain," and GORM
stops being magic and becomes a SQL generator you can reason about.
📝 This teaches the library — it assumes you know Go (structs, methods, pointers, slices — Go From Zero) and basic databases (tables, keys, joins — What a Database Is). The ORM concepts transfer directly from Hibernate & JPA and SQLAlchemy. GORM needs a real database (the examples use SQLite for zero setup) and runs as a Go program, so examples are shown with their output.
How to read this
Read in order — it builds one schema (a small blog: users, posts, comments) from a bare connection up to associations, the N+1 trap, and migrations. Phases carry difficulty badges.
The phases
Part 1 — Foundations (🟢 → 🟡)
- What GORM Is & Connecting 🟢 — the ORM idea, opening a
*gorm.DB, and seeing the SQL it logs. - Models & Auto-Migration 🟡 — structs as tables, tags,
gorm.Model, andAutoMigrate. - Create & Read 🟡 —
Create,First/Find/Take, and how records round-trip.
Part 2 — Real queries (🟡 → 🔴)
4. Querying 🟡 — Where, Order, Limit/Offset, Select, and reusable scopes.
5. Update & Delete 🟡 — Save/Updates, the zero-value trap, and soft vs hard deletes.
6. Associations 🔴 — has-one, has-many, belongs-to, and many-to-many with join tables.
7. Preloading & the N+1 Trap 🔴 — lazy vs Preload/Joins, and the query explosion that bites everyone.
Part 3 — Real projects (🔴 → 🟢)
8. Transactions, Hooks & Migrations 🔴 — Transaction, lifecycle hooks, and why AutoMigrate isn't enough in production.
9. GORM in the Real World & Where to Go Next 🟢 — when to drop to raw SQL, GORM vs sqlc/sqlx, and what to build.
The throughline: a struct is a table, and
*gorm.DBis a query you chain. Keep an eye on the SQL it generates and you stay in command of your database instead of fighting the ORM.