实现一个并发安全、高性能的中间件,可以使用 sync.Pool 来避免频繁的内存分配和垃圾回收,以提高性能。
基于 sync.Pool 实现的 Context
type Context struct {
Req *http.Request
Resp http.ResponseWriter
PathParams map[string]string
data map[string]interface{}
pool *sync.Pool
}
func (ctx *Context) SetData(key string, value interface{}) {
ctx.data[key] = value
}
func (ctx *Context) GetData(key string) (interface{}, bool) {
val, ok := ctx.data[key]
return val, ok
}
func (ctx *Context) reset(req *http.Request, resp http.ResponseWriter, pathParams map[string]string) {
ctx.Req = req
ctx.Resp = resp
ctx.PathParams = pathParams
ctx.data = make(map[string]interface{})
}
func (ctx *Context) Release() {
ctx.pool.Put(ctx)
}
func AcquireContext(pool *sync.Pool, req *http.Request, resp http.ResponseWriter, pathParams map[string]string) *Context {
c := pool.Get().(*Context)
c.reset(req, resp, pathParams)
c.pool = pool
return c
}
调用方式如下:
func handlerFunc(ctx *Context) {
// 处理逻辑
ctx.Resp.Write([]byte("Hello, World!"))
// 释放上下文对象,以便复用
ctx.Release()
}
func middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
// 从 sync.Pool 中获取上下文对象
ctx := AcquireContext(ctxPool, req, resp, nil)
// 在上下文对象中添加需要传递给 handler 的数据
ctx.SetData("key", "value")
// 调用下一个处理器
next.ServeHTTP(resp, req)
})
}
func main() {
// 创建一个 sync.Pool
ctxPool := &sync.Pool{
New: func() interface{} {
return &Context{}
},
}
defer func() {
// 当应用程序退出时,清除 sync.Pool 中的对象
for i := 0; i < 10; i++ {
ctx := ctxPool.Get().(*Context)
ctx.Reset(nil, nil, nil)
ctx.pool = nil
ctxPool.Put(ctx)
}
}()
// 创建路由器
r := NewRouter()
// 添加中间件
r.Use(middleware)
// 添加路由
r.GET("/", handlerFunc)
// 启动 HTTP 服务器
http.ListenAndServe(":8080", r)
}
在 middleware 函数中,从 sync.Pool 中获取一个 Context 对象,并在上下文对象中添加需要传递给 handler 的数据。调用 next.ServeHTTP 方法执行下一个处理器。在 handlerFunc 函数中,从上下文对象中获取需要的数据并进行处理。处理完成后,调用 ctx.Release() 方法释放上下文对象,以便复用。