はじめに
- Go 言語では以下のような簡単なコードでウェブサーバーを立ち上げることができますが、正確に意味を理解しておらずイディオムとして使っていたので整理するために一回ちゃんと調べてみました。
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello World")
})
log.Fatal(http.ListenAndServe(":8080", nil))
}
http.Handler とは
-
http.Handler
とはServeHTTP
関数を持つだけのインターフェイスで HTTP リクエストを受けてレスポンスを返すことを責務とします。
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
http.Handle とは
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
-
http.Handle
とは表示する URL と、URL に対応するhttp.Handler
をDefaultServeMux
に登録する関数です。 -
DefaultServeMux
とはデフォルトでhttp.ServeMux
型の構造体で URL に対応したhttp.Handler
を実行するいわゆるルーターです。 - また
DefaultServeMux
はルーターであると同時にServeHTTP
関数を持つhttp.Handler
です。 -
http.ListenAndServe
の第二引数が nil の場合DefaultServeMux
が Handler として指定されます。自分が分かりづらかったのはここでhttp.ListenAndServe
が Handler を受け取ったりgorilla/mux
のようなルーターを受け取ったりしていたので混乱しました。全てがhttp.Handler
なんだと理解できてからはすっきりしました。 - 以下の 1 と 2 と 3 はだいたい同じ意味の処理になります。
type AnyHandler struct {}
func (a *AnyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {}
anyHandler := &AnyHandler{}
// 1
http.Handle("/any/", anyHandler)
http.ListenAndServe(":8080", nil)
// 2
mux := http.NewServeMux()
mux.Handle("/any/", anyHandler)
http.ListenAndServe(":8080", mux)
// 3
http.ListenAndServe(":8080", http.HandleFunc(func(w http.ResponseWriter, r *http.Request){
if r.URL.Path == "/any/" {
anyHandler.ServeHTTP(w, r)
}
}))
http.HandlerFunc とは
-
func(ResponseWriter, *Request)
の別名の型でServeHTTP
関数を持つので、関数を定義してhttp.HandlerFunc
にキャストするだけで構造体を宣言することなくhttp.Handler
を用意することができます。
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
http.HandleFunc とは
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
- URL と
func(ResponseWriter, *Request)
を渡してDefaultServeMux
に登録する関数です。 - 内部で
func(ResponseWriter, *Request)
からhttp.HandlerFunc
へのキャストが行われています。
さいごに
- 全部ドキュメントに載っていて読めってはなしなのでドキュメント大切。