golang http 中間件


golang http 中間件

源碼鏈接

golang的http中間件的實現 首先實現一個http的handler接口

type Handler interface {
	ServeHTTP(ResponseWriter, *Request)
}

type Router struct {
	route map[string]Handle
}

func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
}

通過函數包裹的方式實現

中間件v1.0

1.通過匿名函數 將handler包裹起來 然后再 調用傳進來的handler。在執行傳進來的參數之前
就可以做到記錄日志 等一些中間件的功能

2.如果有多個中間件 那么就多個函數 一層一層包裹

func withMiddle(h Handle) Handle {
	return func(writer http.ResponseWriter, request *http.Request) {
		t := time.Now()
		defer func() {
			log.Println("time spend is ", time.Since(t))
		}()
		h(writer, request)
	}
}

func (r *Router) Register1(route string, f Handle) {
	r.route[route] = withMiddle(f)
}

func (r *Router) Register2(route string, f Handle) {
	r.route[route] = withMiddLog(withMiddTime(f))
}

Register("/bench", func(writer http.ResponseWriter, request *http.Request) {
    time.Sleep(time.Second)
    fmt.Println("bench sleep 1 second")
})

中間件v1.1

注冊的時候 可以更加簡化一些 通過匿名函數的方式 當然這種方式沒有傳遞參數
只是作為演示用的

func (r *Router) Register(route string, f HandlerFunc) {
	r.route[route] = withMiddLog(withMiddTime(func(writer http.ResponseWriter, request *http.Request) {
		f()
	}))
}

中間件v2.0

針對中間件v1.1中的沒法傳遞 http中的讀寫參數的問題 可以封裝一個context
將http的讀寫參數都包裹進來 這樣就可以很方便的處理讀寫了

func (r *Server) Register(route string, f HandlerFunc) {
	r.route[route] = withMiddLog(withMiddTime(func(writer http.ResponseWriter, request *http.Request) {
		f(r.createContext(writer, request))
	}))
}
r.Register("/bench", func(c *Context) {
		time.Sleep(time.Second)
		fmt.Println("bench sleep 1 second")
		c.Writer.Write([]byte("hello!\r\n"))
	})

golang框架gin中的實現

中間件v3.0

核心理念是將中間件和最后的函數 一視同仁 。通過一個for循環遍歷具體的可以參考代碼

func (c *Context) Next() {
	c.index++
	//for中的index++是為了退出循環 否則沒法退出
	for ; c.index < len(c.middle); c.index++ {
		c.middle[c.index](c)
	}
}

func withMiddTime() HandleContext {
	return func(c *Context) {
		t := time.Now()
		defer func() {
			fmt.Println("withMiddTime end time", time.Since(t))
		}()
		fmt.Println("withMiddTime start ", time.Since(t))
		c.Next()
	}
}
func (s *Server) Register(path string, f ...HandleContext) {
	handleNew := make([]HandleContext, 0, len(s.handle)+len(f))
	handleNew = append(handleNew, s.handle...)
	handleNew = append(handleNew, f...)
	s.routeHandler(path, func(writer http.ResponseWriter, request *http.Request) {
		s.createContext(writer, request, handleNew).Next()
	})
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM