Skip to content

golang http 包源码简介(中间件实现原理/函数作为接口):

下面4段代码都可以开启一个http服务,他们有什么区别呢?

type myHandler struct {
}

func (h myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "Hello from a HandleFunc #1!\n")
}
func http1() {
	h := myHandler{}
	log.Fatalln(http.ListenAndServe(":8000", h))
}

func http2() {
	h := myHandler{}
	http.Handle("/hello", &h)
	log.Fatalln(http.ListenAndServe(":8000", nil))
}


var h = func(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello"))
}

func http3() {
	http.ListenAndServe(":8000", http.HandlerFunc(h))
}

func http4() {
	http.HandleFunc("/hello", h)
	http.ListenAndServe(":8000", nil)
}

http2 相对 http1 多了 一个路径解析.

http1 和 http3 是什么区别呢?

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)
}

http1 一个是类(myHandler)实现了接口(Handler).

http3 一个是函数(HandlerFunc)也可以实现接口(Handler).

然后看一下 如何实现中间件:

func Wrapper(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("before wrap\n"))
		h.ServeHTTP(w, r)
		w.Write([]byte("after wrap\n"))
	})
}

func wrap1() {
	h := myHandler{}
	log.Fatalln(http.ListenAndServe(":8000", Wrapper(h)))
}

func wrap2() {
	http.ListenAndServe(":8000", Wrapper(http.HandlerFunc(h)))
}