日志中间件通过包装http.Handler记录请求信息,可实现请求路径、方法、响应状态码和处理时间的自动日志输出,支持标准输出或文件写入,提升Go Web项目调试与监控能力。

在Golang Web项目中,日志记录中间件可以帮助我们自动记录每次HTTP请求的基本信息,比如请求路径、方法、响应状态码、处理时间等,便于调试和监控。下面是一个简单但实用的日志中间件实现方式,适用于基于
net/http或类似框架(如Gin、Echo)的项目。
1. 基础日志中间件设计
中间件本质上是一个函数,接收
http.Handler并返回一个新的
http.Handler。在这个新处理器中,我们可以记录请求前后的信息。
以下是一个通用的日志中间件实现:
package main
import (
"log"
"net/http"
"time"
)
// 日志中间件
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 请求开始时间
start := time.Now()
// 调用下一个处理器
next.ServeHTTP(w, r)
// 记录日志
log.Printf(
"%s %s %s %dms",
r.RemoteAddr,
r.Method,
r.URL.Path,
time.Since(start).Milliseconds(),
)
})
}
2. 使用中间件包装路由
在主函数中,你可以将具体的处理器通过日志中间件进行包装。
立即学习“go语言免费学习笔记(深入)”;
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, World!"))
})
// 使用中间件包装 mux
loggedMux := loggingMiddleware(mux)
log.Println("Server starting on :8080")
http.ListenAndServe(":8080", loggedMux)
}
这样,每次访问
/hello,都会在控制台输出类似:
127.0.0.1:54321 GET /hello 2ms
3. 支持自定义日志输出(如写入文件)
你可以将日志输出到文件而不是标准输出,只需替换
log的输出目标。
func init() {
logFile, err := os.OpenFile("access.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Fatal("无法打开日志文件:", err)
}
log.SetOutput(logFile)
}
这样所有通过
log.Printf输出的内容都会写入
access.log文件。
4. 增强功能:记录响应状态码
上面的中间件无法直接获取响应状态码,因为
ResponseWriter不暴露状态码。我们可以通过包装
ResponseWriter来解决。
type loggingResponseWriter struct {
http.ResponseWriter
statusCode int
}
func (lrw *loggingResponseWriter) WriteHeader(code int) {
lrw.statusCode = code
lrw.ResponseWriter.WriteHeader(code)
}
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
// 包装 ResponseWriter
lrw := &loggingResponseWriter{
ResponseWriter: w,
statusCode: http.StatusOK, // 默认状态码
}
next.ServeHTTP(lrw, r)
log.Printf(
"%s %s %s %d %dms",
r.RemoteAddr,
r.Method,
r.URL.Path,
lrw.statusCode,
time.Since(start).Milliseconds(),
)
})
}
现在中间件可以正确记录实际返回的状态码,比如404、500等。
总结通过定义一个接收并返回
http.Handler的函数,我们可以轻松实现日志中间件。关键点包括记录请求时间、包装
ResponseWriter以获取状态码、以及支持输出到文件。这种模式简洁、可复用,适合大多数Go语言Web项目。
基本上就这些,不复杂但容易忽略细节。










