HTTP中间件是通过包装原始handler实现前置处理的函数,不能直接修改http.HandleFunc因ServeMux无拦截能力;必须返回新Handler,按洋葱模型嵌套,常用闭包或结构体封装。
http.HandleFunc
Go 的 http.ServeMux 本身不提供「拦截」能力,http.HandleFunc 注册的是终态处理器(http.HandlerFunc),一旦匹配就直接执行,没有钩子可插。所谓「前置处理」,本质是把原始 handler 包一层新函数,在调用原 handler 前做检查、日志、鉴权等操作——这就是中间件的实现原理。
常见错误是试图在 http.HandleFunc 内部做逻辑判断后跳过后续处理,结果发现无法控制流程(比如想拒绝请求却仍继续执行),根本原因是没理解 Go HTTP 处理链是单向的,必须靠「包装」而非「修改」。
http.Handler 或 http.HandlerFunc
最轻量的写法是闭包:一个接受 http.Handler 并返回新 http.Handler 的函数。它能捕获外部变量(如密钥、白名单),适合配置固定的前置逻辑。
func AuthMiddleware(secret string) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("X-API-Key")
if token != secret {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
next.ServeHTTP(w, r) // 放行给下一层
})
}
}
使用时注意顺序和嵌套方式:
立即学习“go语言免费学习笔记(深入)”;
AuthMiddleware("abc123")(loggingMiddleware(http.HandlerFunc(myHandler))) —— 先鉴权,再打日志,最后进业务next.ServeHTTP(w, r),请求会卡住,无响应也无错误secret 是值拷贝,线程安全;但若传指针或 map,需自行同步当需要复用、组合或动态配置(比如开关日志、设置超时秒数),结构体比闭包更清晰。关键点在于:结构体字段存配置,Wrap 方法返回包装函数,ServeHTTP 实现实际逻辑。
type LoggingMiddleware struct {
Enabled bool
}
func (l LoggingMiddleware) Wrap(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if l.Enabled {
log.Printf("START %s %s", r.Method, r.URL.Path)
defer log.Printf("END %s %s", r.Method, r.URL.Path)
}
next.ServeHTTP(w, r)
})
}
type TimeoutMiddleware struct {
Seconds int
}
func (t TimeoutMiddleware) Wrap(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), time.Duration(t.Seconds)*time.Second)
defer cancel()
r = r.WithContext(ctx)
done := make(chan struct{})
go func() {
next.ServeHTTP(w, r)
close(done)
}()
select {
case <-done:
case <-ctx.Done():
http.Error(w, "Request timeout", http.StatusGatewayTimeout)
}
})
}
这种写法的优势:
Wrap 方法统一接口,方便链式调用:timeout.Wrap(logging.Wrap(handler))
r.WithContext() 替换原请求,否则下游 handler 拿不到新 contexthttp.StripPrefix 不算真正中间件http.StripPrefix 看似是前置处理,但它只修改 r.URL.Path,不干预执行流程,也不支持条件跳过或注入逻辑。它属于路由预处理,不是中间件。真正的中间件必须满足两个条件:能读写 request/response、能决定是否调用 next。
容易混淆的点:
http.StripPrefix("/api", h) 本质是新建一个 http.ServeMux 子路由,不是包装 handlerStripPrefix 和中间件,注意路径已被截断,中间件里看到的 r.URL.Path 是去前缀后的复杂中间件往往要同时处理 context 传递、panic 恢复、body 重放(如鉴权需读 body)、response writer 包装(用于统计状态码)——这些都不是开箱即用的,得一层层自己补全。
# go
# golang
# 处理器
# 编码
# 为什么
# 中间件
# 封装
# Logging
# 结构体
# 指针
# 接口
# 线程
# 闭包
# map
# ide
# http
# 链式
# 跳过
# 的是
# 也不
# 多个
# 这就是
# 已被
# 自定义
# 而非
# 它能
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
网络优化76771 】
【
技术知识130152 】
【
IDC云计算60162 】
【
营销推广131313 】
【
AI优化88182 】
【
百度推广37138 】
【
网站推荐60173 】
【
精选阅读31334 】
相关推荐:
PHP主流架构怎么监控运行状态_工具推荐【操作】
php高频调试功能有哪些_php常用调试函数与工具汇总【解答】
windows 10应用商店区域怎么改_windows 10微软商店切换地区方法
Win11怎么关闭系统提示音_Windows11声音方案设为无声教程
Windows 11怎么设置默认解压软件_Windows 11为ZIP/RAR文件指定默认打开程序
Windows10如何删除恢复分区_Win10 Diskpart命令强制删除分区
Win10系统怎么查看网络连接状态_Windows10网络和共享中心
如何自定义Windows终端的默认配置文件?(PowerShell/CMD)
Win11怎么更改系统语言_Win11中文语言包下载与安装【指南】
php怎么捕获异常_trycatch结构处理运行时错误的技巧【方法】
Windows11怎么自定义任务栏_Windows11任务栏自定义教程【步骤】
c++的STL算法库find怎么用 在容器中查找指定元素【实用教程】
Linux如何安装Golang环境_Linux下Go语言开发包配置【方法】
Mac怎么设置鼠标滚动速度_Mac鼠标设置详细参数
Win11怎么设置虚拟桌面 Win11新建多桌面切换操作【技巧】
win11 OneDrive怎么彻底关闭 Win11禁用并卸载OneDrive教程【分享】
如何使用Golang读取日志文件_Golang bufio Scanner日志处理示例
c++怎么用jemalloc c++替换默认内存分配器【性能】
VSC怎样用终端运行PHP_命令行执行脚本的步骤【教程】
如何使用Golang实现微服务状态监控_Golang服务运行状态采集方法
怎么将XML数据可视化 D3.js加载XML
Mac如何彻底清理浏览器缓存?(Safari与Chrome)
c++怎么调用nana库开发GUI_c++ 现代风格窗口组件与事件处理【实战】
Win11如何设置电源计划_Win11电源计划优化教程【攻略】
微信JSAPI支付回调PHP怎么接收_处理JSAPI异步通知数据方法【指南】
Django 测试数据库表缺失与字段未创建问题的完整解决方案
Win11无法拖拽文件到任务栏怎么办_Win11开启拖放功能修复【方法】
Python深度学习实战教程_神经网络模型构建与训练
Win11怎么设置右键刷新选项_Windows11显示更多选项技巧
php打包exe后无法写入文件_权限问题解决方法【教程】
Mac如何解压zip和rar文件?(推荐免费工具)
mac怎么退出id_MAC退出iCloud账号与Apple ID切换【指南】
Win11怎么设置开机自动连接宽带_Windows11创建拨号连接计划任务
Win11怎么设置闹钟_Windows 11时钟应用闹钟设置指南【详解】
如何更改Windows资源管理器的默认启动位置?(快速访问/此电脑)
Win11键盘快捷键大全_Windows 11常用高效快捷键汇总【技巧】
php怎么下载安装后设置错误日志_phpini log配置教程【汇总】
Win11怎么恢复旧版开始菜单_通过软件还原Win10风格菜单【详解】
Win10如何关闭安全中心所有通知 Win10禁用Windows Defender提醒【设置】
MAC怎么用连续互通相机里的“桌上视角”_MAC在视频通话中同时展示人脸和桌面
Python文件操作优化_大文件与流处理解析【教程】
Win11怎么退出微软账户_切换Win11为本地账户登录方法【详解】
Win11怎么更改盘符_Win11磁盘管理修改驱动器号【步骤】
Win10怎样清理C盘爱奇艺缓存_Win10清理爱奇艺缓存步骤【步骤】
Windows资源管理器总是卡顿或重启怎么办?(修复方法)
php485函数执行慢怎么优化_php485性能提升小技巧【技巧】
php查询数据怎么导出csv_查询结果转csv文件保存【操作】
Go语言中正确反序列化多个同级XML元素为结构体切片的方法
Mac怎么给文件夹加密_Mac创建加密磁盘映像教程【安全】
Windows蓝屏错误0x0000001E怎么修复_KMODEEXCEPTIONNOTHANDLED排查
2026-01-04
致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。