golang gin/httpRouter框架路由中间件use的实现原理

中间件入门
package main

import (
	"fmt"
	"net/http"
	"time"
)
// 写一个路由处理函数
func hello(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello zzh"))
}
// 写一个中间件
func timeMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		timeStart := time.Now()

		next.ServeHTTP(w, r)

		timeElapsed := time.Since(timeStart)
		fmt.Println("处理请求耗时 : ", timeElapsed)
	})
}

func main(){
	http.Handle("/", timeMiddleware(http.HandlerFunc(hello)))
	fmt.Println("start listen port")
	http.ListenAndServe(":12345", nil)
}

httpRouter 中间件
package main

import (
	"fmt"
	"net/http"
	"time"
)
// 声明一个中间件类型
type middleware func(handler http.Handler) http.Handler
// 定义一个路由
type Router struct {
	middlewareChain []middleware
	mux map[string]http.Handler
}

func NewRouter() *Router {
	return &Router{
		mux:make(map[string]http.Handler),
	}
}
// 添加中间件
func (r *Router) Use (m middleware) {
	r.middlewareChain = append(r.middlewareChain, m)
}
// 添加路由
func (r *Router) Add(route string, h http.Handler) {
	var mergedHandler = h
	for i := len(r.middlewareChain) - 1; i>=0; i-- {
		// 倒序 循环构造中间件合集, 类似递归的方式 嵌套组合成一个方法
		mergedHandler = r.middlewareChain[i](mergedHandler)
	}
	// 把最终合成的路由处理方法赋值
	r.mux[route] = mergedHandler
}
// 实现 http.Hander 接口
func (r *Router) ServeHTTP(w http.ResponseWriter, q *http.Request) {
	path := q.URL.Path
	if path == "/hello" {
		r.mux[path].ServeHTTP(w, q)
	} else {
		w.Write([]byte("zzh not find"))
	}
}

// time middle
func timeMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
		timeStart := time.Now().UnixNano() / 1e6

		next.ServeHTTP(w, r)

		timeEnd := time.Now().UnixNano() / 1e6

		timeElapsed := timeEnd - timeStart

		fmt.Println("处理时间:", timeElapsed)
	})
}

func pathMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			fmt.Println("before pathMiddleware")
			fmt.Println(r.URL.Path)
			next.ServeHTTP(w, r)
			fmt.Println("after pathMiddleware")
	})
}

func hello(w http.ResponseWriter, r *http.Request) {
	fmt.Println("this is hello function")
	_, err := w.Write([]byte("hello zzh"))
	if err != nil {
		fmt.Println(err)
	}
}

func main(){
	r := NewRouter()
	r.Use(timeMiddleware)
	r.Use(pathMiddleware)
	r.Add("/hello", http.HandlerFunc(hello))
	//http.HandleFunc("/hello", hello)
	http.ListenAndServe(":12345", r)
}

Golang 中,中间件是一种常见的设计模式,用于在请求处理过程中添加公共功能、处理请求前后的逻辑等。下面是一种常见的 Golang 中间件实现原理: 1. 定义一个中间件函数类型,它接受一个 `http.Handler` 参数,并返回一个新的 `http.Handler` 对象。例如: ```go type MiddlewareFunc func(http.Handler) http.Handler ``` 2. 编写一个具体的中间件函数,它符合上述定义的中间件函数类型。该函数通常会包装原始的 `http.Handler` 对象,添加额外的逻辑或修改请求/响应。 ```go func LoggerMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // 添加日志记录逻辑 log.Println("Handling request:", r.URL.Path) // 调用下一个处理器 next.ServeHTTP(w, r) }) } ``` 3. 在路由处理器中使用中间件。通过将中间件函数应用到路由处理器上,可以实现对该路由及其子路由的请求进行拦截和处理。 ```go func main() { // 创建一个路由router := mux.NewRouter() // 应用中间件路由router.Use(LoggerMiddleware) // 添加路由处理器 router.HandleFunc("/", handler) // 启动服务器 http.ListenAndServe(":8080", router) } ``` 在上述例子中,`LoggerMiddleware` 是一个简单的日志记录中间件,它会在处理每个请求之前输出请求的路径信息。通过调用 `router.Use(LoggerMiddleware)`,该中间件会应用到所有的路由上。 这是一种常见的中间件实现原理,你可以根据自己的需求编写更复杂的中间件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值