Lifecycle Hooks & Middleware
Master middleware execution order and lifecycle
This example demonstrates how middleware creates before/after hooks around handlers.
Middleware Execution Flow
Request
↓
[Global Middleware]
↓
[Route Middleware 1] → Before
↓
[Route Middleware 2] → Before
↓
[Handler] → Main logic
↓
[Route Middleware 2] → After
↓
[Route Middleware 1] → After
↓
Response
Key Concept: ctx.Next()
func middleware(ctx *request.Context) error {
// Code BEFORE ctx.Next() runs BEFORE handler
fmt.Println("Before handler")
// Call next middleware/handler
err := ctx.Next()
// Code AFTER ctx.Next() runs AFTER handler
fmt.Println("After handler")
return err
}
Patterns
Pattern 1: Before Hook
func beforeMiddleware(ctx *request.Context) error {
fmt.Println("Setup work")
ctx.Set("start_time", time.Now())
return ctx.Next()
}
Pattern 2: After Hook
func afterMiddleware(ctx *request.Context) error {
err := ctx.Next() // Execute handler first
// Cleanup or post-processing
duration := time.Since(ctx.Get("start_time"))
fmt.Printf("Duration: %v\n", duration)
return err
}
Pattern 3: Around Hook (Before + After)
func loggingMiddleware(ctx *request.Context) error {
start := time.Now()
fmt.Println("→ Request started")
err := ctx.Next()
fmt.Printf("← Request finished in %v\n", time.Since(start))
return err
}
Pattern 4: Short-circuit
func authMiddleware(ctx *request.Context) error {
if !isAuthorized(ctx) {
// Don't call ctx.Next() - stop here
return ctx.Api.Unauthorized("Not authorized")
}
return ctx.Next() // Continue to handler
}
Middleware Order
Per-Route Middleware
router.GET("/path", handler,
middleware1, // Executes 1st (before)
middleware2, // Executes 2nd (before)
middleware3, // Executes 3rd (before)
)
// Handler executes
// middleware3 after
// middleware2 after
// middleware1 after
Global + Route Middleware
router.Use(globalMiddleware) // Runs first
router.GET("/path", handler, routeMiddleware) // Runs second
Group Middleware
group := router.AddGroup("/api")
group.Use(groupMiddleware) // Applies to all routes in group
group.GET("/users", handler) // groupMiddleware → handler
Use Cases
| Pattern | Use Case | Example |
|---|---|---|
| Before | Setup, validation | Request ID, auth check |
| After | Cleanup, logging | Duration tracking, audit log |
| Around | Timing, tracing | Performance monitoring |
| Short-circuit | Auth, rate limit | Stop if unauthorized |
Running
go run main.go
# Watch console output to see middleware execution order
Key Takeaways
✅ Middleware wraps handlers with before/after logic
✅ ctx.Next() executes the next middleware/handler
✅ Code before ctx.Next() = before hook
✅ Code after ctx.Next() = after hook
✅ Middleware executes in order, then unwinds in reverse
✅ Short-circuit by NOT calling ctx.Next()