# 3.4 Goのhttpパッケージ詳細
前の節でGoが如何にWebの作業モードを実現するかフローをご紹介しました。この節では、httpパッケージを詳しく解剖していきます。これはどのように全体のプロセスを実現しているのでしょうか。

Goのhttpには２つのコアとなる機能があります：Conn、ServeMux

## Connのgoroutine
我々が普段書くhttpサーバとは異なり、Goはマルチスレッドと高い性能を実現するため、goroutinesを使ってConnのイベント読み書きを処理します。これによって各リクエストは独立性を保持することができます。互いにブロックせず、効率よくネットワークイベントにレスポンスすることができます。これがGoに高い効率を保証します。

Goがクライアントのリクエストを待ち受けるには以下のように書きます：

	c, err := srv.newConn(rw)
	if err != nil {
		continue
	}
	go c.serve()

クライアントの各リクエストはどれもConnを一つ作成しているのがわかるかと思います。このConnには今回のリクエストの情報が保存されています。これは目的のhandlerに渡され、このhandlerで目的のhandler情報を読み取ることができます。このように各リクエストの独立性を保証します。

## ServeMuxのカスタム定義
前の節でconn.serverについてご説明した際、拾は内部ではhttpパッケージのデフォルトのルートをコールしていました。ルータを通して今回のリクエストのデータをバックエンドの処理関数に渡します。ではこのルータはどのように実現されているのでしょうか？

構造は以下のとおりです：

	type ServeMux struct {
		mu sync.RWMutex   //ミューテックス、リクエストがマルチスレッド処理に及んだことでミューテックス機構が必要になります。
		m  map[string]muxEntry  // ルーティングルール、一つのstringがひとつのmuxエンティティに対応します。ここではstringは登録されるルーティングを表現しています。
		hosts bool // 任意のルールにhost情報が含まれているか
	}

以下でmuxEntryを見てみましょう

	type muxEntry struct {
		explicit bool   // 精確にマッチするか否か
		h        Handler // このルーティング式はどのhandlerに対応するか
		pattern  string  //マッチング文字列
	}

次にHandlerの定義を見てみましょう。

	type Handler interface {
		ServeHTTP(ResponseWriter, *Request)  // ルーティング実現器
	}

Handlerはインターフェースですが、前の節の中で`sayhelloName`関数が特にServerHTTPというインターフェースを実装してはいませんでした。どうして追加できるのでしょうか？もともとhttpパッケージの中では`HandlerFunc`という型を定義しています。この型はデフォルトでServerHTTPインターフェースを実装しています。つまり、HandlerFunc(f)をコールして強制的にfをHandlerFunc型に型変換しているのです。このようにしてfはServerHTTPメソッドを持つことになります。

	type HandlerFunc func(ResponseWriter, *Request)

	// ServeHTTP calls f(w, r).
	func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
		f(w, r)
	}

ルータでは対応するルーティングルールを保存した後、具体的にはどのようにリクエストを振り分けているのでしょうか？以下のコードをご覧ください。デフォルトのルータは`ServerHTTP`を実装します：

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

上に示す通りルータはリクエストを受け取った後、`*`であれば接続を切断し、そうでなければ`mux.handler(r).ServerHTTP(w, r)`をコールして対応する設定された処理Handlerを返し、`h.ServeHTTP(w, r)`を実行します。

つまり、目的のルーティングのhandlerのServerHTTPインターフェースへのコールです。ではmux.Handler(r)はどのように処理するのでしょうか？

	func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
		if r.Method != "CONNECT" {
			if p := cleanPath(r.URL.Path); p != r.URL.Path {
				_, pattern = mux.handler(r.Host, p)
				return RedirectHandler(p, StatusMovedPermanently), pattern
			}
		}	
		return mux.handler(r.Host, r.URL.Path)
	}
	
	func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {
		mux.mu.RLock()
		defer mux.mu.RUnlock()

		// Host-specific pattern takes precedence over generic ones
		if mux.hosts {
			h, pattern = mux.match(host + path)
		}
		if h == nil {
			h, pattern = mux.match(path)
		}
		if h == nil {
			h, pattern = NotFoundHandler(), ""
		}
		return
	}

もともとこれはユーザのリクエストしたURLとルータの中に保存されているmapのマッチングに従って、このhandlerのServHTTPインターフェースをコールすることで目的の関数を実行することができます。

上の紹介を通じて、ルーティングの全体プロセスを理解しました。これはHandlerインターフェースです。つまり外部のルータはHandlerインターフェースを実装するだけで良く、自分自身で実装したルータのServHTTPの中でカスタムに定義されたルータ機能を実現することができます。

下のコードを通して、自分自身で簡単なルータを実装してみます。

	package main

	import (
		"fmt"
		"net/http"
	)

	type MyMux struct {
	}

	func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path == "/" {
			sayhelloName(w, r)
			return
		}
		http.NotFound(w, r)
		return
	}

	func sayhelloName(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello myroute!")
	}

	func main() {
		mux := &MyMux{}
		http.ListenAndServe(":9090", mux)
	}

## Goのコードの実行プロセス

httpパッケージへの分析を通して、全体のコードの実行プロセスを整理してみましょう。

- まずHttp.HandleFuncをコールします。

	順序にしたがっていくつかの事を行います：

	1 DefaultServerMuxのHandlerFuncをコールする。

	2 DefaultServerMuxのHandleをコールする。

	3 DefaultServerMuxのmap[string]muxEntryで目的のhandlerとルーティングルールを追加する。

- 次にhttp.ListenAndServe(":9090", nil)をコールする。

	順序にしたがっていくつかの事を行う：

	1 Serverのエンティティ化

	2 ServerのListenAndServe()をコールする

	3 net.Listen("tcp", addr)をコールし、ポートを監視する

	4 forループを起動し、ループの中でリクエストをAcceptする

	5 各リクエストに対してConnを一つエンティティ化し、このリクエストに対しgoroutineを一つ開いてgo c.serve()のサービスを行う。

	6 各リクエストの内容を読み込むw, err := c.readRequest()

	7 handlerが空でないか判断する。もしhandlerが設定されていなければ（この例ではhandlerは設定していません）、handlerはDefaultServeMuxに設定されます。

	8 handlerのServeHttpをコールする

	9 この例の中では、この後DefaultServerMux.ServeHttpの中に入ります

	10 requestに従ってhandlerを選択し、このhandlerのServeHTTPに入ります

		mux.handler(r).ServeHTTP(w, r)

	11 handlerを選択します：

	A ルータがこのrequestを満足したか判断します（ループによってServerMuxのmuxEntryを走査します。）

	B もしルーティングされれば、このルーティングhandlerのServeHttpをコールします。

	C ルーティングされなければ、NotFoundHandlerのServeHttpをコールします

## links
   * [目次](<preface.md>)
   * 前へ: [Goはどのようにしてweb作業を行うか](<03.3.md>)
   * 次へ: [概要](<03.5.md>)
