处理器

在go语言中。一个处理器就是一个拥有ServeHTTP方法的接口,这个ServeHTTP方法需要两个参数:第一个参数是一个ResponseWriter接口,而第二个参数则是一个指向Request结构的指针

那么也就是说,任何接口只要有一个ServeHTTP方法,并且该方法带有以下的签名,那么他就是一个处理器

ServeHttp(w http.ResponseWriter, r *http.Request)

那么为什么在ListenAndServe中第二个参数接受的是一个处理器,它的默认值却是DefaultServeMux(多路复用器)呢?

因为DefaultServeMux多路复用器是ServeMux结构的一个实例,而ServeMux也拥有ServeHTTP方法

所以DefaultServeMux既是ServeMux结构的实例,同时也是Handler结构的实例。那么DefaultServeMux不仅是多路复用器,还是一个处理器。不过它是一个特殊的处理器,我们需要他做的就是将不同的URL重定向到不同的处理器

单个处理器的使用方法:

package main

import (
    "fmt"
    "net/http"
)

type Handler struct{}

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    hello := "Hello Wrold!"
    fmt.Fprintf(w, "%s\n", hello)
}

func main() {

    index := Handler{}

    server := &http.Server{
        Addr:    "0.0.0.0:9090",
        Handler: &index,
    }

    err := server.ListenAndServe()

    if err != nil {
        fmt.Println(err)
    }
}

使用多个处理器

大部分情况下,我们不希望仅使用一种处理器处理所有请求。所以我们可以通过http.Handle函数将处理器绑定至默认的DefaultServeMux

package main

import (
    "fmt"
    "net/http"
)

type Index struct{}

func (h *Index) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    hello := "Hello Wrold!"
    fmt.Fprintf(w, "%s\n", hello)
}

type Login struct{}

func (h *Login) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "You are in the login\n")
}

type Home struct{}

func (h *Home) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "You are in the home\n")
}

type News struct{}

func (h *News) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "You are in the news\n")
}

func main() {

    index := Index{}
    login := Login{}
    home := Home{}
    news := News{}

    server := &http.Server{
        Addr: "0.0.0.0:9090",
    }

    http.Handle("/", &index)
    http.Handle("/login", &login)
    http.Handle("/home", &home)
    http.Handle("/news", &news)

    err := server.ListenAndServe()

    if err != nil {
        fmt.Println(err)
    }
}
虽然Handle函数来源于http包,但是它实际上是ServeMux的某个方法:这些是为了操作便利而创建的,比如调用http.Handle实际上就是调用DefaultServeMux中的Handle方法

处理器函数

处理器函数就是与处理器有相同行为的函数:这些函数与ServeHTTP方法有相同的签名

package main

import (
    "fmt"
    "net/http"
)

func index(w http.ResponseWriter, r *http.Request) {
    hello := "Hello Wrold!"
    fmt.Fprintf(w, "%s\n", hello)
}

func login(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "You are in the login\n")
}

func home(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "You are in the home\n")
}

func news(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "You are in the news\n")
}

func main() {

    server := &http.Server{
        Addr: "0.0.0.0:9090",
    }

    http.HandleFunc("/", index)
    http.HandleFunc("/login", login)
    http.HandleFunc("/home", home)
    http.HandleFunc("/news", news)

    err := server.ListenAndServe()

    if err != nil {
        fmt.Println(err)
    }
}

参考文档

1、郑兆雄 著 黄建宏 译. Go Web编程[[M]. 北京:人民邮电出版社. 2017.12:56-61

Last modification:October 28, 2019
If you think my article is useful to you, please feel free to appreciate