如何使用Golang实现Web日志记录_使用中间件记录请求信息

Go Web日志中间件通过包装http.Handler拦截请求,记录方法、路径、状态码、耗时、客户端IP等;需自定义ResponseWriter捕获状态码和响应字节数,建议结构化输出并过滤敏感信息。

在 Go Web 开发中,用中间件记录请求日志是最常用、最轻量也最可控的方式。核心思路是:在 HTTP 处理链的入口处拦截请求,记录方法、路径、状态码、耗时、客户端 IP 等关键信息,再交给后续 handler 处理。

定义日志中间件函数

中间件本质是一个接收 http.Handler 并返回新 http.Handler 的函数。它包装原始 handler,在执行前后插入日志逻辑:

  • 使用 time.Now() 记录开始时间,time.Since() 计算耗时
  • req.RemoteAddrX-Forwarded-For 头提取真实客户端 IP
  • 创建自定义 ResponseWriter 包装器,捕获写入时的状态码和响应字节数
  • 日志建议用结构化格式(如 JSON)或标准字段对齐的文本,方便后续解析

捕获响应状态码和字节数

Go 的 http.ResponseWriter 默认不暴露状态码和写入长度,需自行封装:

  • 定义一个结构体,内嵌 http.ResponseWriter,并添加 statuswritten 字段
  • 重写 WriteHeader(statusCode int) 方法,保存状态码
  • 重写 Write(p []byte) (int, error) 方法,累加写入字节数,并在首次写入时补调 WriteHeader(http.StatusOK)
  • 这样就能在 defer 的日志语句中准确拿到最终状态码和响应体大小

集成到 HTTP 路由中

net/http 为例,直接用 http.Handlehttp.HandleFunc 套一层中间件即可:

  • http.Handle("/api/", loggingMiddleware(http.StripPrefix("/api", apiHandler)))
  • 若用 Gin,可用 router.Use(Logger());Echo 则是 e.Use(middleware.Logger())(内置)
  • 生产环境建议搭配日志库如 zapzerolog,支持异步写入、滚动切割、JSON 输出等
  • 避免在日志中打印敏感内容(如 Authorization、密码、身份证号),可对 Header 或 Query 做白名单过滤

基本上就这些。不复杂但容易忽略细节——尤其是状态码捕获和 client IP 的正确提取。写一次,所有路由自动受益。