You implement middleware outside HTTP by creating a generic function wrapper that accepts a core handler and returns a new handler with added behavior. This pattern relies on Go's first-class functions and the ability to compose handlers through closures, just like http.Handler chains.
type Handler func(ctx context.Context) error
func LoggingMiddleware(next Handler) Handler {
return func(ctx context.Context) error {
log.Println("Request started")
err := next(ctx)
log.Println("Request finished")
return err
}
}
func AuthMiddleware(next Handler) Handler {
return func(ctx context.Context) error {
if !isAuthenticated(ctx) {
return errors.New("unauthorized")
}
return next(ctx)
}
}
func main() {
coreHandler := func(ctx context.Context) error {
// Business logic
return nil
}
// Chain middleware: Auth -> Logging -> Core
finalHandler := AuthMiddleware(LoggingMiddleware(coreHandler))
finalHandler(context.Background())
}