Go Web编程 第三章--接收请求

net/http标准库

net/http标准库通常包括两个部分,客户端和服务器,我们可以通过ListenAndServe创建一个简陋的服务器

package main

import (
    "net/http"
)

func main() {
    http.ListenAndServe("", nil)
}

这会使用默认的80端口进行网络连接,并且使用默认的多路复用器DefaultServeMux,我们也可以通过Server结构进行更详细的配置

func main() {
    server := http.Server {
        Addr: "127.0.0.1:80",
        Handler: nil,
    }
    server.ListenAndServe()
}

处理器和处理函数

处理器

前面的代码会返回404响应,因为我们还没有为请求编写相应的处理器。一个处理器就是一个拥有ServeHTTPf方法的接口

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

我们通过实现这个接口来编写处理器

type MyHandler struct{}

func (h *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, world")
}

func main() {
    handler := MyHandler{}
    server := http.Server {
        Addr: "127.0.0.1:80",
        Handler: &handler,
    }
    server.ListenAndServe()
}

我们可以设置多个处理器

type HelloHandler struct{}

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

type WorldHandler struct{}

func (world *WorldHandler) ServeHTTP(w http.ResponseWriter, r *http.Reuest) {
    fmt.Fprintf(w, "world!")
}

func main() {
    hello := HelloHandler{}
    world := WorldHandler{}

    server := http.Server {
        Addr: "127.0.0.1:80",
    }
    http.Handle("/hello", &hello)
    http.Handle("/world", &world)

    server.ListenAndServe()
}

我们看一下Handle函数再源码中的定义

func Handle(pattern string, handler Handler) { 
    DefaultServeMux.Handle(pattern, handler) 
}

实际上是在调用DefaultServeMux的某个方法,前面我们已经提到过了DefaultServeMux是个默认多路复用器,实际上它也是个Handler处理器,因为他是ServeMux结构的一个实例,而ServeMux也实现了Handler接口的ServeHTTP方法。这样就可以对不同的请求做出不同的响应。

处理器函数

处理器函数是与处理器拥有同样行为的函数,它们与ServeHTTP拥有同样的函数签名。

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

func main() {
    server := http.Server {
        Addr: "127.0.0.1:8080",
    }
    http.HandleFunc("/hello", hello)

    server.ListenAndServe()
}

HandleFunc是Go语言拥有的一种函数类型,它可以把一个带有正确签名的f转换为带有方法f的handler。
来看看HandleFunc的源码

func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    DefaultServeMux.HandleFunc(pattern, handler)
}

func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    if handler == nil {
        panic("http: nil handler")
    }
    mux.Handle(pattern, HandlerFunc(handler))
}

Handle函数是不是似曾相识!

串联多个处理器和处理器函数

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

func log(h http.Handler) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("Log!")
        h(w, r)
    }
}

func main() {
    server := http.Server {
        Addr: "127.0.0.1:8080",
    }
    http.HandleFunc("/hello", log(hello))
    server.ListenAndServe()
}

其中HandlerFunc是实现了Handler接口的函数类型,源码定义:

type HandlerFunc func(ResponseWriter, *Request)

func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}

ServeMux

ServeMux是一个HTTP请求多路复用器,负责接收HTTP请求并根据请求中的URL将请求重定向到正确的处理器。ServeMux包含一个映射,这个映射会将URL映射至相应的处理器。值得一提的是,ServeMux无法使用变量实现URL模式匹配,因此必要时我们完全可以用其它自建的多路复用器来代替ServeMux,如HttpRouter等高效轻量的第三方复用器

posted @ 2018-12-30 14:57  authetic  阅读(253)  评论(0编辑  收藏  举报