※注意: この記事ははあくまで個人学習用に整理しただけの記事で、内容としては不完全なものになります。読んでも参考にならない可能性が高いです。
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)
}
}
なるほど。一旦雑に理解。