執筆メモ: Go言語のhttpサーバーをスッキリ理解するための3つの型
対象読者
Goを使っているWebアプリケーションのプロジェクトに入ったが、基本的なフレームワークが初めから整備されていて、普段書いているコードの下側がどうなっているかよくわからない人
Goのhttpサーバーを使うコードを書いたことがあるが、いまいちイメージが頭に残っていなくてわかった気になれずにいる人
アピール
全てのサンプルコードはGo playgroundで動かしながら読むことができます
使うためのサンプルコードではなく、理解するためのサンプルコードを書きます
サンプルコードでグローバル変数を使わないので、重要な型がどう連携しているかわかりやすい
よくあるサンプルではグローバル変数を使った短いコードが使われることが多いです
書くこと
net/httpのサーバー機能の基本になる重要な型のメンタルモデル
書かないこと
内部実装
サードパーティフレームワーク
盛り込みたい内容
HTTPのおさらい
HTTP2だと違う
HTTPリクエストを受け取り、HTTPレスポンスを返すのがHTTPサーバー
多分直リンクしない方がいい
Go言語のnet/http
HTTPクライアントに使う関数・型と、HTTPサーバーに使う関数・型の両方を提供する
この記事で扱うのはHTTPサーバーだけ
Go言語のnet/httpのHTTPサーバーを実現する3つの型
http.Handler
http.Server
http.ServeMux
デフォルトのグローバルインスタンスを使わないサンプルコード
HandlerとServerが登場する
Handlerは*http.Requestを受け取ってhttp.ResponseWriterに書き込むだけ
補足: 「http.Responseを返す」設計になっていないのはなぜ?
例えば巨大なレスポンスを返す場合、ストリーム処理になっているとメモリの必要量を低くできる
類似する例として、Goの標準ライブラリでio.Writerを受け取る設計になっているものが多数ありますが、全部目的は同じです
Server
実際の通信を待ち受けてHTTPリクエストを*http.Request型の値に変換する
パースとか呼ぶこともある
変換した*http.RequestをHandlerに渡すhttps://gyazo.com/f595b3a2fe767706da11beb2a1b528b4
問題: どんなリクエストにも1つのハンドラーで対応しなければならない
通常、リクエストのpath(URLの一部)によって対応させるハンドラーを切り替えたい
切り替える機能を持ったハンドラーを作れると嬉しい
Answer: http.ServeMux
http.ServeMux
http.Handerインターフェースを実装する型として提供される
http.ServeMuxはhttp.Handlerの一種だということ
ServeMuxを使い、グローバルインスタンスを使わないサンプルコード