golang 中介軟體如js閉包,亦似python中裝飾器。本質走的還是偏函式,柯里化,只不過執行改造成管道式。
Basic
http
幾個相關的概念
http.Handler
只有一個ServeHTTP
操作的介面http.HandlerFunc
適配普通函式為HTTP handlers
http.Handle
允許用正則字串在DefaultServeMux
上註冊http.Handler
示例 日誌中介軟體 將 http.HandlerFunc
作為入參,作了包裝並返回新的http.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 協議》,轉載必須註明作者和本文連結