处理器和处理器函数

处理器
一个处理器就是实现了Handler这个接口:

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

实现一个处理器:

//定义一个处理器
type MyHandler struct{}
//实现Handler接口
func (h *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "hi")
}

func main() {
    handler := MyHandler{}
    //将处理器绑定在服务器上
    server := http.Server{
        Addr:    "127.0.0.1:8000",
        Handler: &handler,
    }
    server.ListenAndServe()
}

多路复用器DefaultServeMux是一个特殊的处理器,它的任务是根据请求的URL将请求重定向到不同的处理器。DefaultServeMux是http包默认提供的一个多路复用器:

//定义多个处理器
type h1 struct{}
func (h1 *h1) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "h1")
}

type h2 struct{}
func (h2 *h2) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "h2")
}

func main() {
    h1 := h1{}
    h2 := h2{}
    //nil表明服务器使用默认的多路复用器DefaultServeMux
    server := http.Server{
        Addr:    "0.0.0.0:8080",
        Handler: nil,
    }
    //handle函数调用的是多路复用器DefaultServeMux.Handle方法
    http.Handle("/h1", &h1)
    http.Handle("/h2", &h2)

    server.ListenAndServe()
}

处理器函数
处理器函数就是与ServeHTTP方法拥有相同签名的函数。
处理器函数的实现原理:Go语言拥有一种HandlerFunc函数类型,它可以把一个带有正确签名的函数f转换成一个带有方法f的Handler:

func hel(w http.ResponseWriter, r *http.Request) {  
    fmt.Fprintf(w, "hello, world!")
}
h := HandlerFunc(hel)  //将处理器函数转换成处理器

Handler的定义:

type HandlerFunc func(ResponseWriter, *Request)

// 在ServeHTTP方法里调用 f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}

处理器函数只不过是创建处理器的便捷方法而已:

func b1(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "hello")
}

func main() {
    http.HandleFunc("/b1", b1)  //使用http包默认的多路复用器实例绑定
    http.ListenAndServe("127.0.0.1:8080", nil)  //使用http包默认的服务器实例,并开启监听
}

串联多个处理器和处理器函数
诸如日志记录、安全检查和错误处理这样的操作常称为横切点关注,虽然这些操作非常常见,但是为了防止代码重复和代码依赖问题,我们又不希望这些操作和正常的代码混在一起。所以,我们可以使用串联技术分隔代码中的横切关注点。

func hello(w http.ResponseWriter, r *http.Request)  {
    fmt.Fprintf(w, "hello world!!")
}

func log(h http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        fmt.Printf(" time: %s| handlerfunc:%s\n", time.Now().String(), runtime.FuncForPC(reflect.ValueOf(h).Pointer()).Name())
        h(w, r)
    }
}

func main() {
    http.HandleFunc("/", log(hello))
    http.ListenAndServe(":8080", nil)
}

串联多个处理器时:

func log22(h http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ...
        h.ServeHTTP(w, r)
    })
}

多路复用器
ServeMux是一个HTTP请求多路复用器,它负责接收HTTP请求并根据请求中的URL将请求重定向到正确的处理器。ServeMux本身是处理器。DefaultServeMux是ServeMux的一个实例。

URL处理规则:被绑定的URL不以/结尾,那么它只会与完全相同的URL匹配。被绑定的URL以/结尾,那么只有前缀相同,那么ServeMux也会匹配两个URL。

ServeMux的一个缺陷是无法使用变量实现URL模式匹配,第三方库HttpRouter则可以:

func hee(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
    fmt.Fprintf(w, "hello!%s\n", p.ByName("name"))
}

func main() {
    mux := httprouter.New()
    mux.GET("/hello/:name", hee)
    mux.GET("/hello/", hee)
    s := http.Server{
        Addr:    "127.0.0.1:8080",
        Handler: mux,
    }
    s.ListenAndServe()
}

猜你喜欢

转载自blog.csdn.net/weixin_42506905/article/details/82185550