Hooks and Scopes
Customize queries.
Hooks and Scopes is a free Go Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Go Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Hooks and Scopes
GORM offers two customization tools: hooks run code automatically around lifecycle events, and scopes package reusable query logic. Together they keep your data access clean and consistent.
What Are Hooks
Hooks are methods on your model that GORM calls before or after an operation: BeforeCreate, AfterCreate, BeforeUpdate, BeforeDelete, and more.
A BeforeCreate Hook
Define a method with the right signature on the model. Here we set a UUID before the record is inserted.
func (u *User) BeforeCreate(tx *gorm.DB) error {
u.UUID = uuid.NewString()
return nil
}Validation in Hooks
Return an error from a hook to abort the operation. GORM rolls back the surrounding transaction, so invalid data never reaches the database.
func (u *User) BeforeSave(tx *gorm.DB) error {
if u.Age < 0 {
return errors.New("age cannot be negative")
}
return nil
}Hooks Run in a Transaction
The tx *gorm.DB argument is the transaction GORM is using. If you write related data inside a hook, use this tx so it commits or rolls back atomically with the main operation.
What Are Scopes
A scope is a function that takes and returns a *gorm.DB, encapsulating a query fragment. You apply it with db.Scopes(...) and reuse it across many queries.
func ActiveUsers(db *gorm.DB) *gorm.DB {
return db.Where("active = ?", true)
}Applying Scopes
Pass one or more scopes to Scopes. They compose, so you can combine filters declaratively into a final query.
db.Scopes(ActiveUsers, Recent).Find(&users)A Runnable Hook and Scope Simulation
GORM needs a database, so this runnable example simulates a BeforeCreate hook and a reusable scope-like filter with plain functions.
package main
import (
"errors"
"fmt"
)
type User struct {
Name string
Age int
Active bool
}
func beforeCreate(u *User) error {
if u.Age < 0 {
return errors.New("age cannot be negative")
}
if u.Name == "" {
u.Name = "anonymous"
}
return nil
}
func activeOnly(users []User) []User {
var out []User
for _, u := range users {
if u.Active {
out = append(out, u)
}
}
return out
}
func main() {
u := User{Age: 30, Active: true}
if err := beforeCreate(&u); err != nil {
fmt.Println("error:", err)
return
}
fmt.Println("created:", u.Name)
all := []User{u, {Name: "Lin", Active: false}}
fmt.Println("active count:", len(activeOnly(all)))
}Scopes for Pagination
A common scope generates pagination from a page number, encapsulating Offset and Limit so every list endpoint paginates the same way.
func Paginate(page, size int) func(*gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB {
return db.Offset((page - 1) * size).Limit(size)
}
}Hooks vs Application Logic
Hooks centralize cross-cutting concerns like timestamps, slugs, and audit fields. Keep heavy business logic in services, not hooks, so behavior stays predictable and testable.
Skipping Hooks
For bulk operations you can disable hooks with db.Session(&gorm.Session{SkipHooks: true}). This speeds large imports but skips your validations, so use it carefully.
Quick Check
Test your hooks and scopes knowledge.
Recap
You learned hooks and scopes:
- Hooks run around lifecycle events; returning an error aborts and rolls back
- Hooks run inside the transaction via the tx argument
- Scopes are reusable *gorm.DB functions applied with Scopes
- Use scopes for filters and pagination
- SkipHooks bypasses hooks for bulk work
Frequently asked questions
Is the “Hooks and Scopes” lesson free?
Yes — the full text of “Hooks and Scopes” is free to read here on the web, and the Go Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Go Academy course, upgrade to CoddyKit PRO.
What will I learn in “Hooks and Scopes”?
Customize queries. You practise Go Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Go Academy?
No prior experience is required. Go Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Hooks and Scopes” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Go Academy lesson?
Yes. Every Go Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Models and AutoMigrate
- CRUD Operations
- Associations
- Hooks and Scopes