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