ServeMux
Golang中的路由(即 Multiplexer )基于 ServeMux 结构,先看一下 ServeMux 的定义:
type ServeMux struct {
mu sync.RWMutex
m map[string]muxEntry
es []muxEntry // slice of entries sorted from longest to shortest.
hosts bool // whether any patterns contain hostnames
}
type muxEntry struct {
h Handler
pattern string
}
这里重点关注 ServeMux 中的字段 m ,这是一个 map , key 是路由表达式, value 是一个 muxEntry 结构, muxEntry 结构体存储了对应的路由表达式和 handler 。
值得注意的是, ServeMux 也实现了 ServeHTTP 方法:
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
if r.RequestURI == "*" {
if r.ProtoAtLeast(1, 1) {
w.Header().Set("Connection", "close")
}
w.WriteHeader(StatusBadRequest)
return
}
h, _ := mux.Handler(r)
h.ServeHTTP(w, r)
}
也就是说 ServeMux 结构体也是 Handler 对象,只不过 ServeMux 的 ServeHTTP 方法不是用来处理具体的 request 和构建 response ,而是用来确定路由注册的 handler 。
注册路由
搞明白 Handler 和 ServeMux 之后,我们再回到之前的代码:
DefaultServeMux.Handle(pattern, handler)
这里的 DefaultServeMux 表示一个默认的 Multiplexer ,当我们没有创建自定义的 Multiplexer ,则会自动使用一个默认的 Multiplexer 。
然后再看一下 ServeMux 的 Handle 方法具体做了什么:
func (mux *ServeMux) Handle(pattern string, handler Handler) {
mux.mu.Lock()
defer mux.mu.Unlock()
if pattern == "" {
panic("http: invalid pattern")
}
if handler == nil {
panic("http: nil handler")
}
if _, exist := mux.m[pattern]; exist {
panic("http: multiple registrations for " + pattern)
}
if mux.m == nil {
mux.m = make(map[string]muxEntry)
}
// 利用当前的路由和handler创建muxEntry对象
e := muxEntry{h: handler, pattern: pattern}
// 向ServeMux的map[string]muxEntry增加新的路由匹配规则
mux.m[pattern] = e
// 如果路由表达式以'/'结尾,则将对应的muxEntry对象加入到[]muxEntry中,按照路由表达式长度排序
if pattern[len(pattern)-1] == '/' {
mux.es = appendSorted(mux.es, e)
}
if pattern[0] != '/' {
mux.hosts = true
}
}
Handle 方法主要做了两件事情:一个就是向 ServeMux 的 map[string]muxEntry 增加给定的路由匹配规则;然后如果路由表达式以 '/' 结尾,则将对应的 muxEntry









