【初学者向け】golangのListenAndServeについてまとめてみた。

Webサーバを構築してくれるListenAndServeについてまとめてみました。

```golang:main.go
func main() {
	http.ListenAndServe(":8080", nil)
}
```
```golang:server.go
// ListenAndServe listens on the TCP network address addr and then calls
// Serve with handler to handle requests on incoming connections.
// Accepted connections are configured to enable TCP keep-alives.
//
// The handler is typically nil, in which case the DefaultServeMux is used.
//
// ListenAndServe always returns a non-nil error.
func ListenAndServe(addr string, handler Handler) error {
	server := &Server{Addr: addr, Handler: handler}
	return server.ListenAndServe()
}
```

ListenAndServeは、ポート番号(string型)とハンドラ(Handler型)の引数を取ります。
このハンドラの引数にnilが渡された場合、デフォルトでDefaultServeMuxというServeMux型のハンドラが使用されます。
ソースのコメントにもあるように、基本的にnilを渡すのが正解のようなので、深追いしません。(初学者なので)

この二つの引数をもとに、Webサーバが起動し、リクエスト受付状態になります。

```golang:server.go
// ListenAndServe listens on the TCP network address srv.Addr and then
// calls Serve to handle requests on incoming connections.
// Accepted connections are configured to enable TCP keep-alives.
//
// If srv.Addr is blank, ":http" is used.
//
// ListenAndServe always returns a non-nil error. After Shutdown or Close,
// the returned error is ErrServerClosed.
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(tcpKeepAliveListener{ln.(*net.TCPListener)})
}
```

レシーバが使われてますね。server型のポインタならListenAndServeが使えるようです。


```golang:server.go
// Serve accepts incoming connections on the Listener l, creating a
// new service goroutine for each. The service goroutines read requests and
// then call srv.Handler to reply to them.
//
// HTTP/2 support is only enabled if the Listener returns *tls.Conn
// connections and they were configured with "h2" in the TLS
// Config.NextProtos.
//
// Serve always returns a non-nil error and closes l.
// After Shutdown or Close, the returned error is ErrServerClosed.
func (srv *Server) Serve(l net.Listener) error {
...
	for {
		rw, e := l.Accept()
		if e != nil {
			...
		}
		tempDelay = 0
		c := srv.newConn(rw)
		c.setState(c.rwc, StateNew) // before Serve can return
		go c.serve(ctx)
	}
}
```
Serveメソッドの中で無限ループの最後で、goroutine上でserveメソッドが使用されています。


```golang:server.go
// Serve a new connection.
func (c *conn) serve(ctx context.Context) {
...
	serverHandler{c.server}.ServeHTTP(w, w.req)
...
}

func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
	handler := sh.srv.Handler
	if handler == nil {
		handler = DefaultServeMux
	}
	if req.RequestURI == "*" && req.Method == "OPTIONS" {
		handler = globalOptionsHandler{}
	}
	handler.ServeHTTP(rw, req)
}
```
ServeHTTPメソッドの中まで追ってようやくhandlerにDefaultServerMuxをセットしていることが分かりました。
handlerの役割は、ResponseWriterにリクエストを書き込むことなので、ゴールが近そうです。

```golang:server.go
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
	if r.RequestURI == "*" {
		if r.ProtoAtLeast(1, 1) {
			w.Header().Set("Connection", "close")
		}
		w.WriteHeader(StatusBadRequest)
		return
	}
	h, _ := mux.Handler(r)
	h.ServeHTTP(w, r)
}

// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
	f(w, r)
}
```
ServeMux(マルチプレクサ?)のHandlerメソッドの中で、リクエストのURLパスにマッチするHandlerFuncが返されます。
最終的に返されたHandlerFuncに対して、ResponseWriterとリクエストを投げて、処理を行っています。