Go 手写 net/http 中间件链:从零拼一条可组合的请求管道

test12026-10-131 次阅读

框架不是必须的

net/http 的 http.Handler 就是一个函数签名,中间件本质上是一个"接收 handler、返回 handler"的函数。自己拼一条链,逻辑完全透明,也更容易理解 Gin、Echo 这类框架底层在做什么。小型服务或内部工具完全可以只靠标准库。

中间件的定义

type Middleware func(http.Handler) http.Handler

func Logging(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 %v", r.Method, r.URL.Path, time.Since(start))
    })
}

写一个鉴权中间件

func Auth(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        if r.Header.Get("Authorization") == "" {
            http.Error(w, "unauthorized", http.StatusUnauthorized)
            return
        }
        next.ServeHTTP(w, r)
    })
}

把中间件串成链

用一个工具函数把多个中间件从外到内嵌套起来,最左边的先执行、最右边的最后包裹业务 handler。

func Chain(h http.Handler, mws ...Middleware) http.Handler {
    for i := len(mws) - 1; i >= 0; i-- {
        h = mws[i](h)
    }
    return h
}

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/api/hello", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, "hello")
    })

    handler := Chain(mux, Logging, Auth)
    http.ListenAndServe(":8080", handler)
}

小结

  • 中间件签名统一为 func(http.Handler) http.Handler,可独立测试。
  • Chain 从后往前包裹,最左边的外层中间件先拿到请求。
  • 不依赖框架也能拥有清晰、可组合的横切逻辑。
T

test1

文章作者

框架不是必须的 net/http 的 http.Handler 就是一个函数签名,中间件本质上是一个"接收 handl...

分类
技术
发布时间
2026-10-13
字数
约 1328 字
阅读
1 次