※注意: この記事ははあくまで個人学習用に整理しただけの記事で、内容としては不完全なものになります。読んでも参考にならない可能性が高いです。

ServeMux と DefaultServeMux の違いについて、具体的に把握したい。

ServeMux については不完全な内容ながら以下にメモした。
Go の ServeMux について

DefaultServeMux とは

公式ドキュメントには以下のようにコメントしてある。
https://golang.org/src/net/http/server.go?h=defaultServeMux#L2240

DefaultServeMux is the default ServeMux used by Serve.
DefaultServeMuxは、Serveが使用するデフォルトのServeMuxです。

var DefaultServeMux = &defaultServeMux

var defaultServeMux ServeMux

defaultServeMux は単なる変数名で、ServeMux 構造体のポインタが格納されている。

以下にはこのようにコメントがある
https://golang.org/src/net/http/server.go?h=defaultServeMux#L2527

// A Server defines parameters for running an HTTP server.
// The zero value for Server is a valid configuration.
type Server struct {
    Addr string

    Handler Handler // handler to invoke, http.DefaultServeMux if nil

handler to invoke, http.DefaultServeMux if nil
呼び出すハンドラ。 nil の場合は http.DefaultServeMux

そして、その実装が以下

// serverHandler delegates to either the server's Handler or
// DefaultServeMux and also handles "OPTIONS *" requests.
type serverHandler struct {
    srv *Server
}

func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
    handler := sh.srv.Handler
    if handler == nil {
        handler = DefaultServeMux // ここで DefaultServeMux が使用されている
    }
    if req.RequestURI == "*" && req.Method == "OPTIONS" {
        handler = globalOptionsHandler{}
    }
    handler.ServeHTTP(rw, req)
}

なるほど。結局 ServeMux と DefaultServeMux は同じ型だった。

ちなみに、上記の serverHander.ServeHTTP は以下で実行されている
https://golang.org/src/net/http/server.go?h=serve#L1925

func (c *conn) serve(ctx context.Context) {
    // 省略
    serverHandler{c.server}.ServeHTTP(w, w.req) // ここで実行

conn.serve は以下で実行されている
https://golang.org/src/net/http/server.go?h=serve#L2969

func (srv *Server) Serve(l net.Listener) error {
    // 省略
        go c.serve(connCtx) // ここで実行

Server.Serve は以下で実行されている
https://golang.org/src/net/http/server.go?h=serve#L2866

func (srv *Server) ListenAndServe() error {
    if srv.shuttingDown() {
        return ErrServerClosed
    }
    addr := srv.Addr
    if addr == "" {
        addr = ":http"
    }
    ln, err := net.Listen("tcp", addr)
    if err != nil {
        return err
    }
    return srv.Serve(ln) // ここで実行
}

Server.ListenAndServe は直接実行する場合もあるし、http. ListenAndServe から実行されることもある。
http.ListenAndServe 内の server.ListenAndServe 実行箇所は以下。
https://golang.org/src/net/http/server.go?h=serve#L3120

func ListenAndServe(addr string, handler Handler) error {
    server := &Server{Addr: addr, Handler: handler}
    return server.ListenAndServe() // ここで実行
}

例えば、以下のようにサーバーを作成した場合、DefaultServeMux ではなく http.NewServeMux() で作成した mux が使用されるが、

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", index)
    server := &http.Server{
        Addr:           config.Address,
        Handler:        mux, // Handler に mux を設定した場合、DefaultServeMux ではなくこれが使用される
        ReadTimeout:    time.Duration(config.ReadTimeout * int64(time.Second)),
        WriteTimeout:   time.Duration(config.WriteTimeout * int64(time.Second)),
        MaxHeaderBytes: 1 << 20,
    }
    server.ListenAndServe()
}

以下のようにサーバーを作成した場合は、 DefaultServeMux が使用されるということか。

func main() {
    http.Handle("/", &templateHandler{filename: "index.html"})
    // この場合、マルチプレクサを特に設定していない事になるため、DefaultServeMux が使用される
    if err := http.ListenAndServe(":8080", nil); err != nil {
        log.Fatal("ListenAndServe:", err)
    }
}

なるほど。一旦雑に理解。

广告
将在 10 秒后关闭
bannerAds