goweb中间件

中间件基本概念

中间件(Middleware)是一种在HTTP请求到达最终处理程序(Handler)之前或之后执行特定功能的机制。

在 Go 语言里,net/http 是标准库中用于构建 HTTP 服务器的包,中间件则是处理 HTTP 请求时常用的技术。中间件其实就是一个函数,它会接收一个 http.Handler 类型的参数,并且返回另一个 http.Handler。中间件能够在请求到达最终处理程序之前或者响应返回客户端之前执行一些通用操作,像日志记录、认证、压缩等。

下面是一个简单的中间件函数示例:

go 复制代码
go
package main

import (
    "log"
    "net/http"
)

// 中间件函数,接收一个 http.Handler 并返回另一个 http.Handler
func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // 在请求处理之前执行的操作
        log.Printf("Received request: %s %s", r.Method, r.URL.Path)

        // 调用下一个处理程序
        next.ServeHTTP(w, r)

        // 在请求处理之后执行的操作
        log.Printf("Request completed: %s %s", r.Method, r.URL.Path)
    })
}

// 最终处理程序
func helloHandler(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello, World!"))
}

func main() {
    // 创建一个新的 mux
    mux := http.NewServeMux()

    // 应用中间件到最终处理程序
    mux.Handle("/", loggingMiddleware(http.HandlerFunc(helloHandler)))

    // 启动服务器
    log.Println("Server started on :8080")
    log.Fatal(http.ListenAndServe(":8080", mux))
}
  • 中间件函数 loggingMiddleware:
  • 它接收一个 http.Handler 类型的参数 next,代表下一个要执行的处理程序。
  • 返回一个新的 http.HandlerFunc,在这个函数里可以执行请求处理前后的操作。
  • next.ServeHTTP(w, r) 这行代码会调用下一个处理程序。
  • 最终处理程序 helloHandler:

helloHandler是实际处理请求的函数,它会向客户端返回 "Hello, World!"。

中间件链式调用

多个中间件可以串联起来形成处理链:

go 复制代码
package main

import (
    "log"
    "net/http"
)

// 日志中间件
func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        log.Printf("Received request: %s %s", r.Method, r.URL.Path)
        next.ServeHTTP(w, r)
        log.Printf("Request completed: %s %s", r.Method, r.URL.Path)
    })
}

// 认证中间件
func authMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // 简单的认证逻辑
        authHeader := r.Header.Get("Authorization")
        if authHeader != "Bearer secret_token" {
            http.Error(w, "Unauthorized", http.StatusUnauthorized)
            return
        }
        next.ServeHTTP(w, r)
    })
}

// 最终处理程序
func helloHandler(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello, World!"))
}

func main() {
    mux := http.NewServeMux()

    // 应用多个中间件到最终处理程序
    finalHandler := loggingMiddleware(authMiddleware(http.HandlerFunc(helloHandler)))
    mux.Handle("/", finalHandler)

    log.Println("Server started on :8080")
    log.Fatal(http.ListenAndServe(":8080", mux))
}
  • 这里新增了一个 authMiddleware 中间件,用于简单的认证。
  • 在 main 函数里,先把 authMiddleware 应用到 helloHandler 上,再把 loggingMiddleware 应用到结果上,这样就实现了多个中间件的组合。

通过使用中间件,能够让代码更具模块化和可维护性,并且可以在多个处理程序之间共享通用的逻辑。

中间件链中传递自定义参数

​场景​ ​:需要在多个中间件间共享数据(如请求ID、用户会话)

​实现方式​ ​:通过 context.Context 传递参数

go 复制代码
package main

import (
	"context"
	"fmt"
	"net/http"
)

// 中间件函数
func middleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// 设置上下文值
		ctx := context.WithValue(r.Context(), "key", "value")
		ctx = context.WithValue(ctx, "user_id", 123)
		r = r.WithContext(ctx)

		// 调用下一个处理函数
		next.ServeHTTP(w, r)
	})
}

// 处理函数
func handler(w http.ResponseWriter, r *http.Request) {
	// 从上下文中获取值
	value := r.Context().Value("key").(string)
	userID := r.Context().Value("user_id").(int)
	fmt.Fprintf(w, "Received user_id %d value: %v", userID, value)
}

func main() {
	// 创建一个处理函数
	mux := http.NewServeMux()
	mux.HandleFunc("/", handler)

	http.Handle("/", middleware(mux))

	// 启动服务器
	fmt.Println("Server started on :80")
	http.ListenAndServe(":80", nil)
}

​特点​​:

  • 数据在中间件链中透明传递
  • 避免全局变量和参数层层传递

相关推荐
踏着七彩祥云的小丑6 小时前
Go学习第9天:并发编程 + 文件操作 + 正则表达式
学习·golang·正则表达式·go
止语Lab10 小时前
Go 代码生成的三层认知:从忍住不用到自己造轮子
go
协享科技11 小时前
AI 视频理解:让 Agent 看视频并总结内容
人工智能·go·音视频·agent·ai编程
曲幽1 天前
掏出手机就能搭个 WebDAV 同步服务器?这操作有点香
go·termux·tampermonkey·sync·webdav·filebrowser·gowebdav·koreader
Code_Artist2 天前
🦜用 GoAI 从零打造一个 AI Agent 脚手架工程:重新定义智能体开发范式!
go·agent·ai编程
ShuiShenHuoLe2 天前
OS的常用函数
go
踏着七彩祥云的小丑2 天前
Go学习第8天:接口 + 泛型 + 错误处理
开发语言·学习·golang·go
蓝宝石的傻话3 天前
rpi-cam:给 Raspberry Pi 造的轻量级 ONVIF 相机服务
go·iot·nvr
蓝宝石的傻话3 天前
VictoriaMetrics指标流聚合三年回顾与现状(2026)
go·prometheus·victoriametrics
踏着七彩祥云的小丑3 天前
Go学习第7天:Map集合 + 递归函数 + 类型转换
开发语言·学习·golang·go