以下のコードがあったとする。
どちらもやっていること同じじゃないか?と思い調査した結果。
http.Handle("/any/", anyHandler)
http.ListenAndServe(":8080", nil)
mux := http.NewServeMux()
mux.Handle("/any/", anyHandler)
http.ListenAndServe(":8080", mux)
結論
どちらも内部的にやっていることは基本的に同じでした。
http.Handle()
URLパターンと対応するhandlerをDefaultServeMuxの中に登録している。
実装としては以下の形。
// Handle registers the handler for the given pattern
// in the DefaultServeMux.
// The documentation for ServeMux explains how patterns are matched.
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
DefaultServeMuxとは
DefaultServeMux
はServeMuxのポインタ型が格納されている変数。
では、ServeMuxとは
HTTPのマルチプレクサ。
実装としては以下のようになっている。
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
}
http.Handle()の中心はDefaultServeMux.Handle(pattern, handler)
URLパターンと対応するhandlerをDefaultServeMuxの中に登録している。
と記載したがそれはつまり、 DefaultServeMux.Handle(pattern, handler)
の部分。
ServeMux.m
にURLパターンと対応するハンドラを追加している。
実装としては以下。
// Handle registers the handler for the given pattern.
// If a handler already exists for pattern, Handle panics.
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)
}
e := muxEntry{h: handler, pattern: pattern}
mux.m[pattern] = e
if pattern[len(pattern)-1] == '/' {
mux.es = appendSorted(mux.es, e)
}
if pattern[0] != '/' {
mux.hosts = true
}
}
http.NewServeMux().Handle()
URLパターンと対応するhandlerをServeMuxの中に登録している。
実装としては以下。
// Handle registers the handler for the given pattern.
// If a handler already exists for pattern, Handle panics.
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)
}
e := muxEntry{h: handler, pattern: pattern}
mux.m[pattern] = e
if pattern[len(pattern)-1] == '/' {
mux.es = appendSorted(mux.es, e)
}
if pattern[0] != '/' {
mux.hosts = true
}
}
DefaultServeMux.Handle(pattern, handler)
と全く同じ処理ではないか。。
つまり、内部的に http.Handle()
と同じ処理をしている。
改めて結論
冒頭のコードでは全く同じ処理ができる。
ただ、 http.NewServeMux().Handle()
は自分でServeMuxを作成するので
その中の値を独自に変更したい場合などに用いられるのかもしれない。