3. HTTP 基础库与路由:标准库 net/http 详解、http.ServeMux 路由、自定义 Handler 与中间件模式

本章深入 Go 标准库 net/http 的核心机制,从底层处理模型到上层路由构建,再到可复用的中间件模式,为后续实现 API 网关奠定坚实基础。你将掌握如何不依赖第三方框架,仅用标准库搭建出结构清晰、可扩展的 HTTP 服务。

3.1 net/http 核心处理模型:Handler 与 HandlerFunc

net/http 的核心是一个简洁的接口:Handler。任何实现了该接口的类型都可以处理 HTTP 请求。

组件 类型 说明
Handler interface 定义 ServeHTTP(ResponseWriter, *Request) 方法
HandlerFunc func 类型 将普通函数适配为 Handler 的适配器
ServeMux struct 默认的路由多路复用器,实现 Handler 接口
Server struct 监听端口、管理连接、调用 Handler 的运行时容器
关键理解:整个 net/http 服务器就是一个 Handler 链。从 Server 到 ServeMux,再到你的业务逻辑,每一层都实现了 ServeHTTP 方法。
// 最基础的 Handler 实现
type helloHandler struct{}

func (h *helloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello, Go Gateway!"))
}

// 使用 HandlerFunc 适配器
func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
    w.Write([]byte(`{"status":"ok"}`))
}

func main() {
    mux := http.NewServeMux()
    mux.Handle("/hello", &helloHandler{})
    mux.HandleFunc("/health", healthCheckHandler)

    server := &http.Server{
        Addr:    ":8080",
        Handler: mux,
    }
    server.ListenAndServe()
}

3.2 http.ServeMux 路由机制与匹配规则

http.ServeMux 是 Go 标准库内置的路由器,采用前缀匹配策略。理解其匹配规则是避免路由冲突的关键。

路由注册与匹配规则

  • 精确路径:注册 /api 只匹配 /api,不匹配 /api/v1。
  • 子树路径:注册 /api/(以斜杠结尾)匹配 /api/ 及其所有子路径 /api/v1、/api/v1/users。
  • 最长匹配优先:同时注册 / 和 /api/,请求 /api/v1 会匹配 /api/ 而非 /。
  • 根路径兜底:注册 / 会捕获所有未被其他模式匹配的请求,通常用作 404 处理器。
实战建议:在 API 网关中,建议将根路径 / 保留给健康检查和指标端点,将业务路由注册为明确的子树路径,如 /api/v1/、/admin/。
func main() {
    mux := http.NewServeMux()

    // 精确匹配
    mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("health check"))
    })

    // 子树匹配 - 所有 /api/ 开头的请求
    mux.Handle("/api/", http.StripPrefix("/api/", apiHandler()))

    // 根路径兜底
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusNotFound)
        w.Write([]byte("404 - Not Found"))
    })

    http.ListenAndServe(":8080", mux)
}

func apiHandler() http.Handler {
    mux := http.NewServeMux()
    mux.HandleFunc("/users", listUsers)
    mux.HandleFunc("/orders", listOrders)
    return mux
}

3.3 自定义 Handler:构建可组合的 HTTP 处理单元

通过自定义 Handler 结构体,我们可以将请求处理的不同关注点(认证、日志、限流、业务逻辑)封装为独立的处理单元,并通过组合方式构建处理链。

自定义 Handler 组合模式 HTTP 请求 LoggingMiddleware AuthMiddleware BusinessHandler 组合模式优势 • 每个中间件独立职责 • 通过嵌套组合构建链 • 可插拔、可测试
// 自定义 Handler 结构体 - 携带依赖
type UserHandler struct {
    db     *sql.DB
    logger *log.Logger
    cache  *redis.Client
}

func (h *UserHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    // 根据请求方法分发
    switch r.Method {
    case http.MethodGet:
        h.getUser(w, r)
    case http.MethodPost:
        h.createUser(w, r)
    default:
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
    }
}

func (h *UserHandler) getUser(w http.ResponseWriter, r *http.Request) {
    // 从路径中提取 ID
    id := r.URL.Query().Get("id")
    // 业务逻辑...
    w.Write([]byte("user: " + id))
}

3.4 中间件模式:函数式装饰器与链式组合

中间件模式是 Go HTTP 开发的核心模式。一个中间件是一个接收 Handler 并返回 Handler 的函数,通过嵌套调用形成处理链。

标准中间件签名

// 标准中间件签名
type Middleware func(http.Handler) http.Handler

// 链式组合工具
func Chain(handler http.Handler, middlewares ...Middleware) http.Handler {
    for i := len(middlewares) - 1; i >= 0; i-- {
        handler = middlewares[i](handler)
    }
    return handler
}

实战中间件示例

// 请求日志中间件
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 (%v)",
            r.Method, r.URL.Path, r.RemoteAddr, lrw.statusCode, time.Since(start))
    })
}

// 恢复中间件 - 防止 panic 导致进程崩溃
func RecoveryMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        defer func() {
            if err := recover(); err != nil {
                log.Printf("PANIC: %v", err)
                http.Error(w, "Internal Server Error", http.StatusInternalServerError)
            }
        }()
        next.ServeHTTP(w, r)
    })
}

// CORS 中间件
func CORSMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Access-Control-Allow-Origin", "*")
        w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
        w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
        if r.Method == http.MethodOptions {
            w.WriteHeader(http.StatusNoContent)
            return
        }
        next.ServeHTTP(w, r)
    })
}

// 使用示例
func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/api/users", userHandler)

    // 链式组合中间件
    handler := Chain(mux,
        RecoveryMiddleware,
        LoggingMiddleware,
        CORSMiddleware,
    )

    server := &http.Server{
        Addr:    ":8080",
        Handler: handler,
    }
    server.ListenAndServe()
}
注意:中间件的执行顺序与组合顺序相反。在 Chain 函数中,最后一个传入的中间件最先执行。上述示例中,请求到达顺序为:CORS → Logging → Recovery → ServeMux。

3.5 路由与中间件集成架构

将路由、中间件和业务 Handler 整合为一个清晰的架构,是构建可维护 API 网关的基础。

API 网关路由与中间件集成架构 全局中间件层:Recovery → Logging → CORS → RateLimit http.ServeMux 路由分发 /api/v1/ /admin/ /health Auth + Validation AdminAuth + Audit 无中间件 UserHandler DashboardHandler HealthHandler

完整集成示例

// 路由分组与中间件集成
func setupRouter() http.Handler {
    mux := http.NewServeMux()

    // 健康检查 - 无需中间件
    mux.HandleFunc("/health", healthHandler)

    // API v1 路由组 - 需要认证和验证
    apiV1 := http.NewServeMux()
    apiV1.HandleFunc("/users", userHandler)
    apiV1.HandleFunc("/orders", orderHandler)

    // 为 API 路由组添加子中间件
    apiHandler := Chain(apiV1,
        ValidationMiddleware,
        AuthMiddleware,
    )
    mux.Handle("/api/v1/", http.StripPrefix("/api/v1", apiHandler))

    // 管理后台 - 需要管理员认证和审计
    admin := http.NewServeMux()
    admin.HandleFunc("/dashboard", dashboardHandler)
    admin.HandleFunc("/config", configHandler)

    adminHandler := Chain(admin,
        AuditMiddleware,
        AdminAuthMiddleware,
    )
    mux.Handle("/admin/", http.StripPrefix("/admin", adminHandler))

    // 全局中间件
    return Chain(mux,
        RecoveryMiddleware,
        LoggingMiddleware,
        CORSMiddleware,
        RateLimitMiddleware,
    )
}

func main() {
    handler := setupRouter()
    server := &http.Server{
        Addr:    ":8080",
        Handler: handler,
    }
    log.Fatal(server.ListenAndServe())
}
架构要点:全局中间件处理横切关注点(日志、恢复、CORS),路由组中间件处理业务相关关注点(认证、验证),业务 Handler 只关注核心逻辑。这种分层架构使得每个组件职责单一,易于测试和替换。