Instead of duplicating code to implement common/middleware functionality, I like to just pass around functions. I usually just have one makeStandardHandler type function that covers most cases. For the special cases, I can easily combine middleware in any order for the desired result.
// Execution timing middleware
func makeTimingHandler(fn func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
requestStartTime := time.Now()
fn(w, r)
totalRequestTime := time.Now().Sub(requestStartTime)
log.Printf("URL: %s TIME: %s", r.URL.Path, totalRequestTime.String())
}
}
// Serve up one file
func makeSingleFileHandler(file string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, file)
}
}
func main() {
...
http.HandleFunc("/robots.txt", makeTimingHandler(makeSingleFileHandler("./s/robots.txt")))
http.HandleFunc("/", makeTimingHandler(indexHandler))
...
}