
本文介绍如何利用 go 标准库 `net/http` 的中间件式设计,在所有路由处理器执行前统一运行预处理逻辑(如 ip 黑名单校验),无需修改业务 handler,兼容 `http.servemux`、gorilla mux 等任意 `http.handler` 实现。
在 Go 的 HTTP 生态中,http.Handler 接口(ServeHTTP(http.ResponseWriter, *http.Request))是构建可组合中间件的核心契约。要实现在所有业务处理器之前执行统一逻辑(例如 IP 黑名单拦截、日志记录、身份预验证等),最简洁、标准且零依赖的方式是创建一个包装型 handler —— 即实现 http.Handler 的自定义结构体,它先执行前置检查,再将请求委托给下游 handler。
以下是一个生产就绪的 IP 黑名单校验示例:
type IPBlacklistMiddleware struct {
next http.Handler
}
func (m IPBlacklistMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// 提取真实客户端 IP(注意:生产环境应使用 X-Forwarded-For 并结合可信代理配置)
clientIP := r.RemoteAddr
if blackListed(clientIP) {
http.Error(w, "Access denied: IP address blocked", http.StatusForbidden)
return
}
// 校验通过,继续调用下游处理器(如路由 mux)
m.next.ServeHTTP(w, r)
}
// 使用示例
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/api/users", usersHandler)
mux.HandleFunc("/admin", adminHandler)
// 将整个 mux 包装进前置校验中间件
handler := IPBlacklistMiddleware{next: mux}
log.Println("Server starting on :8080")
log.Fatal(http.ListenAndServe(":8080", handler))
}✅ 关键优势:
- 完全符合 http.Handler 接口规范,与 net/http 原生生态无缝集成;
- 兼容 Gorilla Mux、Chi、HttpRouter 等所有实现了 http.Handler 的路由器(只需将 mux 替换为对应实例);
- 支持链式嵌套(如 IPBlacklistMiddleware{next: AuthMiddleware{next: mux}}),轻松构建中间件栈;
- 无第三方依赖,纯标准库实现,轻量可靠。
⚠️ 注意事项:
- r.RemoteAddr 在反向代理(如 Nginx、Cloudflare)后可能仅为代理地址,需解析 X-Forwarded-For 头并配合 http.Request.TrustProxy 逻辑(推荐使用 realip 等成熟工具提取真实 IP);
- 黑名单检查建议使用高效数据结构(如 map[string]struct{} 或布隆过滤器)避免线性扫描;
- 若需异步或上下文感知(如注入 context.Context),可扩展为接收 http.Handler 并返回 http.Handler 的函数型中间件(即 func(http.Handler) http.Handler),更易复用。
总之,Go 的 Handler 组合模型天然支持“前置执行”,无需框架魔法——只需一次包装,即可全局生效。










