golang 中间件如js闭包,亦似python中装饰器。本质走的还是偏函数,柯里化,只不过执行改造成管道式。
Basic
http
http.HandlerServeHTTPhttp.HandlerFuncHTTP handlershttp.HandleDefaultServeMuxhttp.Handler
http.HandlerFunchttp.HandlerFunc
package main
import (
"fmt"
"log"
"net/http"
)
func logging(f http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
log.Println(r.URL.Path)
f(w, r)
}
}
func foo(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "foo")
}
func bar(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "bar")
}
func main() {
http.HandleFunc("/foo", logging(foo))
http.HandleFunc("/bar", logging(bar))
http.ListenAndServe(":8080", nil)
}
测试
httpie
$ go run basic-middleware.go
2017/02/10 23:59:34 /foo
2017/02/10 23:59:35 /bar
2017/02/10 23:59:36 /foo?bar
$ http :8080/foo
$ http :8080/bar
$ http :8080/foo?bar
Advance
package main
import (
"fmt"
"log"
"net/http"
"time"
)
// 定义中间件类型
type Middleware func(http.HandlerFunc) http.HandlerFunc
func Logging() Middleware {
// 创建中间件
return func(f http.HandlerFunc) http.HandlerFunc {
// 定义 http.HandlerFunc
return func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
defer func() {
log.Println(r.URL.Path, time.Since(start))
}()
// 在链中调用下一个中间件或handler
f(w, r)
}
}
}
// 谓词中间件,确保请求方式是指定的http谓词动作
func Method(m string) Middleware {
return func(f http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != m {
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
return
}
f(w, r)
}
}
}
// 调用链串应用多个中间件产生一个 http.HandlerFunc
// 类似pipe 管道, 上游的输出视为下游的输入
func Chain(f http.HandlerFunc, middlewares ...Middleware) http.HandlerFunc {
for _, m := range middlewares {
f = m(f)
}
return f
}
func Hi(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hi, pardon110")
}
func main() {
http.HandleFunc("/", Chain(Hi, Method("GET"), Logging()))
http.ListenAndServe(":8080", nil)
}
测试
发起请求
C:\Users\Administrator>http post :8080/hi
HTTP/1.1 400 Bad Request
Content-Length: 12
Content-Type: text/plain; charset=utf-8
Date: Fri, 19 Mar 2021 11:17:13 GMT
X-Content-Type-Options: nosniff
Bad Request
C:\Users\Administrator>http :8080/hi
HTTP/1.1 200 OK
Content-Length: 14
Content-Type: text/plain; charset=utf-8
Date: Fri, 19 Mar 2021 11:17:33 GMT
Hi, pardon110
服务端响应
D:\code-base\gomod\tt\web>go run "d:\code-base\gomod\tt\web\middleware\advance\advancet.go"
2021/03/19 19:17:13 /hi 0s
2021/03/19 19:17:33 /hi 0s
本作品采用《CC 协议》,转载必须注明作者和本文链接