Chapter 01

はじめに

さき(H.Saki)
さき(H.Saki)
2021.09.07に更新

この本について

Goのnet/httpパッケージはとても使い勝手がよく、コードを数行書いただけですぐにWebサーバーの"Hello World"ができるようになります。

// Hello Worldの一部
h1 := func(w http.ResponseWriter, _ *http.Request) {
    io.WriteString(w, "Hello from a HandleFunc #1!\n")
}
http.HandleFunc("/", h1)
log.Fatal(http.ListenAndServe(":8080", nil))

自分が使いたいハンドラを書き、それをどこのURL・ポート番号で起動させるかということを宣言的に指定するだけで、簡単にその要件を満たしたWebサーバーが起動します。
ですが、この裏に何が行われているのか考えてみたことはありますか?

筆者はこれをやったときに、

  • net.Listen()とかln.Accept()とかやらなくていいの?
  • リクエストをネットワークから「Readする/読み込む」ような処理がどこにも書かれてないけど、どこでやってるの?
  • http.HandleFunc関数に登録しているハンドラって、どこに行くの?どこに保存されるの?
  • ハンドラに出てくる第一引数http.ResponseWriterって何者?なんでこれに書き込むだけで勝手にレスポンスになるの?
  • そもそもhttp.ListenAndServeの第二引数nilっていいの?

などというポイントが気になってしかたがありませんでした。我ながらめんどくさい性格してると思います

実際にGoのWebサーバーが行っている「コネクションを確立してリクエストを読み込んで……」という手続き的な処理については、net/httpの中にまるっと隠蔽されユーザーが気にしなくていいようになっているので、それを知りたいなら実際にコードリーディングをするのが一番の近道でした。

この本では、当時私が抱いた疑問の答えを見つけるためにnet/httpパッケージのソースコードを読み漁って得た内容を、わかりやすくまとめ図式化したものを共有するために執筆したものとなります。
これを通して、「GoのWebサーバーの中身、ちょっとわかる」となってもらえたら嬉しいです。

本の構成

2章 ウェブサーバーのHello, World

この章では、「サーバーの中身の前に、どうやってGoでサーバーを立てるの?」というところを軽く紹介します。

3章 httpサーバー起動の裏側

ここでは、http.ListenAndServe関数が実行されてから、その第二引数に渡されたルーティングハンドラが起動するところまでのソースコードを追っていき、流れを図示しています。

4章 デフォルトでのルーティング処理の詳細

この章では、ListenAndServe関数の第二引数がnilであった場合、デフォルトで採用されるルータDefaultServeMux

  • ハンドラ登録
  • ハンドリング処理

の仕組みについて、net/httpのソースコードを追って図示しています。

5章 ハンドラによるレスポンス返却の詳細

ここでは、ユーザーが用意したハンドラ関数func(w http.ResponseWriter, _ *http.Request)に関して、

  • 第一引数http.ResponseWriterは何者なのか
  • http.ResponseWriterの書き込みメソッドを実行するだけで、ネットワークに載せるレスポンスが作れてしまうのはどういう仕組みなのか

という2点についてまとめました。

6章 GoでのWebサーバー起動の全体図

最後に、3~5章に渡って説明してきた内容の要点だけを抽出し作成した「Goでウェブサーバーを起動したときに裏で起きている概要図」をここで紹介します。

使用する環境・バージョン

  • OS: macOS Catalina 10.15.7
  • go version go1.17 darwin/amd64

読者に要求する前提知識

  • Goの基本的な文法の読み書きができること