Golang middleware 链式调用
基于web的Golang middleware 链式调用,原文地址在如下 gowebexamples
https://gowebexamples.com/advanced-middleware/
对其调用过程简化及分析如下;
package main import ( "fmt" "time" ) type HandlerFunc func() type Middleware func(HandlerFunc) HandlerFunc func Timing(x int) Middleware { return func(f HandlerFunc) HandlerFunc { return func() { start := time.Now() defer func() { fmt.Println("elapse ", time.Since(start)) }() fmt.Println("in timing", x) f() } } } func Method(s string) Middleware { return func(f HandlerFunc) HandlerFunc { return func() { fmt.Println("in method ", s) f() } } } func Chain(f HandlerFunc, middlerwares ...Middleware) HandlerFunc { for _, m := range middlerwares { f = m(f) } return f } func Hello() { fmt.Println("in Hello") } func iterate(f HandlerFunc) { f() } func main() { iterate(Chain(Hello, Timing(5), Method("get"))) }
调用过程为,在Chain 函数中,Hello 函数作为第一个参数, 调用Timing(5) 后的返回值,匿名函数
func(f HandlerFunc) HandlerFunc,作为第二参数, 调用Method("get")后的返回值,匿名函数作为第三个参数。
遍历每个middleware ,调用第一个Timing(5)的返回值,匿名函数时,将Hello 函数作为参数,此时,匿名函数的返回值中的
f() 即为Hello 函数。返回值为一个包含了Timing 和Hello 函数的 return func() 函数,
将此时的返回值作为参数赋值给调用的Method 函数, 类似于函数入栈
遍历结束后,返回此时的函数,即Method 中的包含打印信息和 f() 的函数。
在iterate 中调用上面的最后一个返回函数,类似于函数出栈,就会依次打印:
in method get
in timing 5
in Hello
elapse 0s
附 : gowebexamples.com 中的Advanced Middleware 如下:
// advanced-middleware.go package main import ( "fmt" "log" "net/http" "time" ) type Middleware func(http.HandlerFunc) http.HandlerFunc // Logging logs all requests with its path and the time it took to process func Logging() Middleware { // Create a new Middleware return func(f http.HandlerFunc) http.HandlerFunc { // Define the http.HandlerFunc return func(w http.ResponseWriter, r *http.Request) { // Do middleware things start := time.Now() defer func() { log.Println(r.URL.Path, time.Since(start)) }() // Call the next middleware/handler in chain f(w, r) } } } // Method ensures that url can only be requested with a specific method, else returns a 400 Bad Request func Method(m string) Middleware { // Create a new Middleware return func(f http.HandlerFunc) http.HandlerFunc { // Define the http.HandlerFunc return func(w http.ResponseWriter, r *http.Request) { // Do middleware things if r.Method != m { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } // Call the next middleware/handler in chain f(w, r) } } } // Chain applies middlewares to a http.HandlerFunc func Chain(f http.HandlerFunc, middlewares ...Middleware) http.HandlerFunc { for _, m := range middlewares { f = m(f) } return f } func Hello(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "hello world") } func main() { http.HandleFunc("/", Chain(Hello, Method("GET"), Logging())) http.ListenAndServe(":8080", nil) }
浙公网安备 33010602011771号