LoginSignup
4
1

More than 3 years have passed since last update.

http.Handle()とhttp.NewServeMux().Handle()について

Last updated at Posted at 2020-11-14

以下のコードがあったとする。
どちらもやっていること同じじゃないか?と思い調査した結果。

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を作成するので
その中の値を独自に変更したい場合などに用いられるのかもしれない。

参考文献

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1