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