go中常用的两种设计模式(装饰器模式)

11 阅读1分钟

func HelloOne(w http.ResponseWriter,r *http.Request){
   fmt.Println("one")
}

func HelloTwo(w http.ResponseWriter,r *http.Request){
   fmt.Println("two")
}

func main() {
   mux:=http.NewServeMux()
   mux.HandleFunc("/router/one",HelloOne)
   mux.HandleFunc("/router/two",HelloTwo)

   svr:=http.Server{
      Addr: "8080",
      Handler: mux,
   }
   svr.ListenAndServe()
}

写了两个接口,假如我需要打印每个接口的耗时,可以直接在方法内部加,如:

func HelloOne(w http.ResponseWriter, r *http.Request) {
   now := time.Now()
   fmt.Println("one")
   fmt.Println("用时:", time.Since(now))
}

func HelloTwo(w http.ResponseWriter, r *http.Request) {
   now := time.Now()
   fmt.Println("two")
   fmt.Println("用时:", time.Since(now))
}

这种做法虽然可以实现,但每个函数都需要去添加,如果有100个函数呢? 为了解决这个问题,我们使用装饰器模式,在不改变原函数的基础上,增强函数功能。

//装饰器
type Handler func(w http.ResponseWriter, r *http.Request)

func Logger(handler Handler) Handler {
   return func(w http.ResponseWriter, r *http.Request) {
      now := time.Now()
      handler(w, r)
      fmt.Println("用时:", time.Since(now))
   }
}

func HelloOne(w http.ResponseWriter, r *http.Request) {
   fmt.Println("one")
}

func HelloTwo(w http.ResponseWriter, r *http.Request) {
   fmt.Println("two")
}

func main() {
   mux := http.NewServeMux()
   //使用Logger
   mux.HandleFunc("GET /router/one", Logger(HelloOne))
   mux.HandleFunc("GET /router/two", Logger(HelloTwo))

   svr := http.Server{
      Addr:    "8080",
      Handler: mux,
   }
   svr.ListenAndServe()
}

但其实我们可以在handler上做装饰器,最终代码:

//装饰器

func Logger(handler http.Handler) http.Handler {
   fn := func(w http.ResponseWriter, r *http.Request) {
      now := time.Now()
      handler.ServeHTTP(w,r)
      fmt.Println("用时:", time.Since(now))
   }
   return http.HandlerFunc(fn)
}

func HelloOne(w http.ResponseWriter, r *http.Request) {
   fmt.Println("one")
}

func HelloTwo(w http.ResponseWriter, r *http.Request) {
   fmt.Println("two")
}

func main() {
   mux := http.NewServeMux()
   mux.HandleFunc("GET /router/one", HelloOne)
   mux.HandleFunc("GET /router/two", HelloTwo)

   svr := http.Server{
      Addr:    "8080",
      Handler: Logger(mux),
   }
   svr.ListenAndServe()
}