制作web应用时,访问一个地址,执行这个地址中的逻辑后返回给客户端一个页面或者数据,访问的地址中的逻辑有许多是相同的,比如只要有人访问某个地址,就记录下访问的时间。相当于在每个处理函数里面都有一句log.Println(),这样会出现许多重复代码。所以我们需要实现的就是调用一个处理器函数完后,调用下一个处理器函数。
package main
import (
"fmt"
"log"
"net/http"
)
func handler(writer http.ResponseWriter, request *http.Request) {
fmt.Fprintf(writer, "hello world!")
}
func loginfo(h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
log.Println()
h(w, r)
}
}
func main() {
http.HandleFunc("/", loginfo(handler))
http.ListenAndServe(":8000", nil)
}
loginfo函数接受一个HandlerFunc类型的函数作为参数,然后返回另一个HandlerFunc类型的函数作为值。loginfo函数返回的是一个匿名函数,因为匿名函数的参数和HandlerFunc类型的参数一致,实际上也就是一个HandlerFunc类型,这样就会先调用loginfo,然后调用handler函数。
这时浏览器访问http://localhost:8000/时,会发现时间输出了2次。这是因为浏览器默认会访问/favicon.ico这个路径,在浏览器上输入http://localhost:8000/aa时,发现还是能够执行,也就是默认情况下,只要匹配/开头的地址都会匹配上处理器函数。先把执行2次的解决掉,在main中加入/favicon.ico的访问路径,对应的函数什么也不做
http.HandleFunc("/", loginfo(handler))
http.HandleFunc("/favicon.ico", hello)
http.ListenAndServe(":8000", nil)
func hello(writer http.ResponseWriter, request *http.Request) {
}
这样就只能执行1次了,使用http.HandleFunc来当做web路由,只能说实现了基本的访问,但是想灵活的应用,使用第三方包会比较好,具体怎么用,我们下次再说。