Golang实现一个基础的中间件示例
技术百科
P粉602998670
发布时间:2026-01-22
浏览: 次 Go HTTP中间件是接收并返回http.Handler的函数,通过闭包在原handler前后插入逻辑;需调用next.ServeHTTP以确保链式执行,顺序影响执行流程,配置应作为参数传入避免共享,panic恢复中间件须置于最外层。
什么是 Go HTTP 中间件
Go 的中间件本质是函数套函数:接收一个 http.Handler,返回一个新的 http.Handler,在调用原 handler 前后插入逻辑。它不是框架内置概念,而是基于 http.Handler 接口和闭包的自然延伸。
最简中间件写法(日志示例)
核心是实现 func(http.Handler) http.Handler 签名。注意别漏掉 next.ServeHTTP(w, r),否则请求就断了。
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Printf("Started %s %s", r.Method, r.URL.Path)
next.ServeHTTP(w, r) // 必须调用,否则下游 handler 不会执行
log.Printf("Completed %s %s", r.Method, r.URL.Path)
})
}
使用时链式包装:
handler := http.HandlerFunc(yourHandler)handler = loggingMiddleware(handler) handler = authMiddleware(handler) // 可叠加多个 http.ListenAndServe(":8080", handler)
带参数的中间件(如允许跨域)
中间件本身可以接受配置参数,返回“中间件工厂函数”。常见错误是把配置写死在闭包外,导致所有实例共享同一份配置。
-
allowedOrigins应作为参数传入,而非全局变量 - 每个
CORS()调用返回独立的中间件实例 - 注意
w.Header().Set()必须在next.ServeHTTP之前设置响应头,否则可能被覆盖
func CORS(allowedOrigins []string) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
origin := r.Header.Get("Origin")
if len(allowedOrigins) == 0 || contains(allowedOrigins, origin) {
w.Header().Set("Access-Control-Allow-Origin", origin)
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
}
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
next.ServeHTTP(w, r)
})
}
}
func contains(slice []string, s string) bool {
for _, v := range slice {
if v == s {
return true
}
}
return false
}
中间件顺序很重要
中间件从外到内执行:第一个包装的最先运行,最后一个包装的最后运行(但它的前置逻辑在 next.ServeHTTP 前,后置逻辑在之后)。比如:
-
loggingMiddleware(authMiddleware(handler)):先打日志 → 再鉴权 → 再执行 handler → 再打完成日志 - 如果鉴权失败,
next.ServeHTTP不会被调用,后续中间件和 handler 都不会执行 - panic 恢复中间件必须放在最外层,才能捕获所有内层 panic
容易忽略的是:中间件内部的 http.Error 或直接写 w.WriteHeader 后再调用 next.ServeHTTP,可能导致重复写 header 报错 http: multiple response.WriteHeader calls。
# ai
# 的是
# 放在
# 很重要
# 多个
# 第一个
# 链式
# 而非
# http
# go
# golang
# Error
# 接口
# 报错
# access
# 闭包
# 中间件
# 全局变量
# 跨域
# 最外层
# 死在
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- 如何在Golang中编写异步函数测试_Golang
- Win10怎样清理C盘爱奇艺缓存_Win10清理爱
- Python类装饰器使用_元编程解析【教程】
- Win11怎么设置任务栏对齐方式_Windows1
- Go 中 defer 语句在 goroutine
- Win10怎样清理C盘浏览器缓存_Win10清理浏
- Win11怎么关闭资讯和兴趣_Windows11任
- C#如何序列化对象为XML XmlSerializ
- Win10系统怎么查看显卡温度_Win10任务管理
- Win11怎么开启空间音效_Windows11耳机
- Win11怎么调整屏幕亮度_Windows 11调
- 如何开启Windows的远程服务器管理工具(RSA
- Win11怎么设置虚拟桌面 Win11新建多桌面切
- Win11搜索栏无法输入_解决Win11开始菜单搜
- PHP的FastAdmin架构适合二次开发吗_特点
- php嵌入式日志记录怎么实现_php将硬件数据写入
- Python如何创建带属性的XML节点
- SAX解析器是什么,它与DOM在处理大型XML文件
- Windows系统被恶意软件破坏后的恢复策略_错误
- 如何在 Go 中正确反序列化 XML 多节点数组(
- Win11怎么关闭防火墙通知_屏蔽Win11安全中
- 如何使用Golang处理静态文件缓存_提高页面加载
- 如何用正则表达式精确匹配最多含一个换行符的起止片段
- Go语言中slice追加操作的底层共享机制解析
- Drupal 中 HTML 链接被双重转义导致渲染
- Win11如何设置ipv6 Win11开启IPv6
- 如何使用Golang实现路由分组管理_Golang
- Windows系统时间服务错误_W32Time服务
- Win10电脑C盘红了怎么清理_Windows10
- php订单日志怎么记录物流_php记录订单物流变更
- 如何使用Golang管理跨项目依赖_Golang多
- 如何解决Windows时间不准的问题?(自动同步设
- Windows 11如何开启文件夹加密(EFS)_
- 如何使用Golang捕获并记录协程panic_保证
- VSC怎么快速定位PHP错误行_错误追踪设置法【方
- Windows笔记本无法进入睡眠模式怎么办?(电源
- Win11如何暂停系统更新 Win11暂停更新最长
- Windows10电脑怎么设置虚拟光驱_Win10
- Windows音频驱动无声音原因解析_声卡驱动错误
- Windows10系统怎么查看CPU核心数_Win
- Windows 11如何查看系统激活密钥_Wind
- c++怎么用jemalloc c++替换默认内存分
- MAC的“接续互通”功能无法使用怎么办_MAC检查
- Win11怎么关闭通知中心_Windows11系统
- Windows7如何安装系统镜像_Windows7
- mac怎么安装字体_MAC添加第三方字体与字体册管
- Python技术债务管理_长期维护解析【教程】
- c# Task.ConfigureAwait(tr
- Win10怎样安装Word样式库_Win10安装W
- Mac怎么安装软件_Mac安装dmg与pkg文件的


QQ客服