注册新的路由和对应Handler

路由

路由就是一个pattern string,原生路由不支持url path method等复杂功能

Handler Interface

原生http调用以下interface来对特定请求进行响应,要求所有的Handler都实现该接口

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

示例

type MyHandle struct {}

func (h MyHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) {  // 实现方法
    fmt.Fprint(w, "hahah") // w.Write([]byte("haha"))
}

以上结构体MyHandle实现了Handler接口,那么可以直接注册

func main() {
    // Handle registers the handler for the given pattern.
    // If a handler already exists for pattern, Handle panics.
    http.Handle("/", MyHandle{})
    http.ListenAndServe(":12345", nil )
}

注册的pattern和Handler被一个map保存起来,由RWLock保护读写

type ServeMux struct {
    mu    sync.RWMutex
    m     map[string]muxEntry   // 这里存放pattern:muxEntry
    hosts bool // whether any patterns contain hostnames
}

type muxEntry struct {
    explicit bool
    h        Handler      // 这个h就是Handler
    pattern  string
}

便捷方法

每次新建一个struct,然后实现ServeHTTP方法(Handler接口)比较烦,而且这个struct只用于实现Handler接口,没有其他用途,所以http package也提供了一个便捷的函数HandleFunc

// DefaultServeMux is the default ServeMux used by Serve.
var DefaultServeMux = &defaultServeMux

var defaultServeMux ServeMux

// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)

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

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

HandleFunc调用了defaultServeMux的HandleFunc方法,在这个方法中,使用类型HandlerFunc将要注册的函数转换为一个实现了ServeHTTP方法的struct,也即实现了Handler interface的struct
然后像示例中一样调用Handle方法注册pattern和新的转换后的Handler

server处理逻辑

http.ListenAndServe用于启动http服务器来实现接口用户request并返回response content
ListenAndServe接口两个参数: host:port string Handler interface,这里的Handler与注册时是一个Handler,但这里用于路由,如果使用默认路由则填nil

示例

func main() {
    http.Handle("/", ImpHandler{})
    http.ListenAndServe(":12345", nil )
}

// ListenAndServe always returns a non-nil error.
func ListenAndServe(addr string, handler Handler) error {
	server := &Server{Addr: addr, Handler: handler}
	return server.ListenAndServe()
}
  1. 在ListenAndServe函数中会新加一个Server struct,这个是http server的一个抽象,包含所有http处理需要的字段信息和方法,然后继续调用各种方法实现监控http服务
  2. server.ListenAndServe // 生成监听socket ln
  3. srv.Serve(ln) // 调用ln.Accept或者con,当新的请求到达时生成一个goroutine处理,把con和srv作为ctx赋给goroutine
  4. go c.serve(ctx) // 生成request和response,而且生成一个新的实现了Handler的serverHandler
  5. serverHandler{c.server}.ServeHTTP(w, w.req) // 该struct需要传入Server的指针,然后调用该struct的ServeHTTP方法并传入request和response,至此,serverHandler获得了执行响应的所有数据和结构(Server、Request、Response)
  6. (sh serverHandler) ServeHTTP(rw ResponseWriter, req Request) // 调用serverHandler.Server.Handler.ServeHTTP方法,这里回到了最开始,也即ListenAndServe时传入的第二个参数,如果是nil,将使用默认http路由,也可以传入定制的路由