0
2

More than 3 years have passed since last update.

【Go】http.ListenAndServe と server.ListenAndServe の違いについて

Last updated at Posted at 2020-08-22

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

http.ListenAndServe と server.ListenAndServe の違い

http.ListenAndServe 使用例

func main() {
    http.Handle("/", &templateHandler{filename: "index.html"})

    if err := http.ListenAndServe(":8080", nil); err != nil {
        log.Fatal("ListenAndServe:", err)
    }
}

server.ListenAndServe() 使用例

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", index)
    server := &http.Server{
        Addr:           config.Address,
        Handler:        mux,
        ReadTimeout:    time.Duration(config.ReadTimeout * int64(time.Second)),
        WriteTimeout:   time.Duration(config.WriteTimeout * int64(time.Second)),
        MaxHeaderBytes: 1 << 20,
    }
    server.ListenAndServe()
}

http パッケージの Server struct を確認
https://golang.org/src/net/http/server.go?h=ListenAndServe#L2520

type Server struct {
    Addr            string
    Handler         Handler // handler to invoke, http.DefaultServeMux if nil
    TLSConfig       *tls.Config
    ReadTimeout     time.Duration
    ReadHeaderTimeout   time.Duration
    WriteTimeout        time.Duration
    IdleTimeout     time.Duration
    MaxHeaderBytes      int
    TLSNextProto        map[string]func(*Server, *tls.Conn, Handler)
    ConnState       func(net.Conn, ConnState)
    ErrorLog        *log.Logger
    BaseContext     func(net.Listener) context.Context
    ConnContext     func(ctx context.Context, c net.Conn) context.Context
    inShutdown      atomicBool
    disableKeepAlives   int32
    nextProtoOnce       sync.Once
    nextProtoErr        error
    mu          sync.Mutex
    listeners       map[*net.Listener]struct{}
    activeConn      map[*conn]struct{}
    doneChan        chan struct{}
    onShutdown      []func()
}

server struct の ListenAndServe method を確認すると

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)
}

上記のようになっており、特に仮引数は受け取らない。

続いて http ListenAndServe 関数を確認

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

こちらは addr 文字列と handler を仮引数で受け取るようになっている。
関数内部で Server struct のポインタで初期化し、server.ListenAndServe() を実行している。

つまり、http.ListenAndServe(":8080", nil) で実行する場合、addr と handler しか指定することができない。また、その際に、マルチプレクサも指定できない為、DefaultServeMux が使用されるという仕組みのようだ。

自分の中の結論としては、

  • addr と handler のみを指定したい場合は http.ListenAndServe を使用
  • addr と handler 以外も指定したい場合は server.ListenAndServe を使用

という理解になった。

0
2
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
0
2