go的http中间件接口问题
通常,http的中间件使用函数方式
func M1(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Println("M1 in")
next.ServeHTTP(w, r)
log.Println("M1 out")
})
}
func M2(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Println("M2 in")
next.ServeHTTP(w, r)
log.Println("M2 out")
})
}
func final(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK"))
}
func main() {
finalHandler := http.HandlerFunc(final)
http.Handle("/", M1(M2(finalHandler)))
http.ListenAndServe(":8080", nil)
}
但这样写不够灵活,比如我要在中间件中依赖其它对象或者想抽象一些方法时不好处理。于是,我想用对象并约定一个中间件接口的方式来使用中间件
type Middleware interface {
Handler(next http.Handler) http.Handler
}
type M1 struct {
Id string
}
type M2 struct {
}
func (this *M1) Handler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Println("M1 in")
log.Printf("M1=%v", this)
this.Id = "hello"
next.ServeHTTP(w, r)
log.Println("M1 out")
})
}
func (this *M2) Handler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Println("M2 in")
next.ServeHTTP(w, r)
log.Println("M2 out")
})
}
func main() {
finalHandler := http.HandlerFunc(final)
m1 := &M1{}
m2 := &M2{}
http.Handle("/", m1.Handler(m2.Handler((finalHandler))))
http.ListenAndServe(":8080", nil)
}
但这样做会有问题,因为m1,m2是在应用启动时初始化的,在不同的请求中,m1,m2指向的是同一个对象。
如例子所示,第一次请求时,m1的Id没有设置,这个时候打印的m1,Id为空。之后m1的Id被设置成hello,这样,第二次请求时,打印的m1,Id的值就是hello。
这个需求,怎么实现比较好?怎么样才能做到每个请求创建一个新的m1?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
可以参考echo里面的中间件JWT的思路,可以封装一个M1的函数,M1这个结构体可以在M1函数里面实现,这样就可以每次都是一个新的对象了。大概是这样: