1. 需求
- 消息中间件可以将业务功能代码和非业务功能代码的解耦
- 支持能够动态地增删中间件
2. HTTP路由相关函数定义
- http.HandleFunc(pattern string, handler func(ResponseWriter, *Request))
- http.Handle(pattern string, handler Handler)
- http.Handle 第二个参数传递的是一个http.Handler接口,而http.HandleFunc第二个参数传递的是一个实现了func(ResponseWriter, *Request)的函数
// Handle registers the handler for the given pattern
// in the DefaultServeMux.
// The documentation for ServeMux explains how patterns are matched.
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
// HandleFunc registers the handler function for the given pattern
// in the DefaultServeMux.
// The documentation for ServeMux explains how patterns are matched.
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
- http.HandlerFunc 是函数func(ResponseWriter, *Request)类型的变量,该变量实现了ServeHTTP接口,所以,可以通过http.HandlerFunc强制转换func(ResponseWriter, *Request)类型的函数,使其满足http.Handler接口
- http.Handler 是接口,含有方法ServeHTTP
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
3. 给http添加timeCost和Logger中间件
- middleware.go
package main
import (
"log"
"net/http"
"os"
"time"
)
var Logger *log.Logger
type middleware func(handler http.Handler) http.Handler
type Router struct {
MiddlewareChain []middleware
Mux map[string]http.Handler
}
func NewRouter() *Router {
return &Router{Mux: make(map[string]http.Handler)}
}
func (r *Router) Use(mid middleware) {
r.MiddlewareChain = append(r.MiddlewareChain, mid)
}
func (r *Router) Add(route string, handler http.Handler) {
var mergeredHandler = handler
for i := len(r.MiddlewareChain) - 1; i >= 0; i-- {
mergeredHandler = r.MiddlewareChain[i](mergeredHandler)
}
Logger.Println("route:", route)
Logger.Printf("handler %+v\n", handler)
r.Mux[route] = mergeredHandler
}
func timeCost(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
timeStart := time.Now()
handler.ServeHTTP(w, r)
timeElapsed := time.Since(timeStart)
Logger.Println("time cost:", timeElapsed)
})
}
func logger(handler http.Handler) http.Handler {
Logger = log.New(os.Stdout, "", 0)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
handler.ServeHTTP(w, r)
})
}
package main
import (
"fmt"
"net/http"
)
func main() {
router := NewRouter()
router.Use(middleware(logger))
router.Use(middleware(timeCost))
router.Add("/hello", http.HandlerFunc(Hello))
http.Handle("/hello", router.Mux["/hello"])
err := http.ListenAndServe(":8080", nil)
if err != nil {
Logger.Fatalln("Http listen error ", err.Error())
}
defer func() {
if p := recover(); p != nil {
Logger.Println("catch panic:", p)
}
}()
}
func Hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%s\n", "hello boy")
}
$ while true; do curl localhost:8080/hello; done
hello boy
hello boy
hello boy
hello boy
hello boy
hello boy
hello boy
$ go run main.go middleware.go
route: /hello
handler 0x64eb90
time cost: 5.713µs
time cost: 5.621µs
time cost: 8.852µs
time cost: 5.478µs
time cost: 9.152µs
time cost: 7.512µs
time cost: 5.521µs
time cost: 46.754µs
time cost: 4.605µs
time cost: 9.383µs
time cost: 5.244µs
time cost: 19.858µs
time cost: 4.372µs
time cost: 16.27µs
time cost: 122.69µs
time cost: 4.319µs