Go
GoDay 20

`Handle`、`HandleFunc`、`Handler`、`HandlerFunc`についてまとめ

More than 5 years have passed since last update.

ただの勉強メモ程度ですが、httpパッケージ配下のHandleHandleFuncHandlerHandlerFuncについてまとめました。

Goでアプリケーションサーバを書くのはとても簡単で、そこらのLL並みの行数で小さなWebアプリケーションが立ち上がる。


httpd-sample.go

package main

import (
"fmt"
"log"
"net/http"
)

func index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello, go httpd!")
}

func main() {
http.HandleFunc("/", index)
e := http.ListenAndServe(":8080", nil)

if e != nil {
log.Panic(e)
}
}


$ go run ./httpd-sample.go

何のログも出ないですが、これで8080番をリスンするっぽい(logパッケージで細かく出してあげれば出る)。

流れは:



  • http.Handlehttp.HandleFunc でパスごとのハンドラーを指定する


  • http.ListenAndServe で立ち上がりる

便利簡単!

http.HandleFunchttp.ResponseWriter*http.Requestを取る関数をそのまま渡せる。

http.Handleは、http.Handlerインタフェースを実装したオブジェクトを渡す。要するにServeHTTP(http.ResponseWriter, *http.Request)という関数を実装したオブジェクトであれば良い。以下のような感じ:


httpd-sample2.go

package main

import (
"fmt"
"net/http"
)

type AppHandler struct {
appName string
}

func(index *AppHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello, %s!", index.appName)
}

func main() {
index := new(AppHandler)
index.appName = "sample app"
http.Handle("/", index)
http.ListenAndServe(":8080", nil)
}


http.HandlerFuncというものもあり、これは関数を渡せばhttp.Handlerを実装したオブジェクトを返してくれる。

http.HandlerFuncは実際にはfunc(ResponseWriter, *Request)の別名だが、ServeHTTPをちゃんと実装している。ServeHTTPは自分自身をただ呼び出すだけである。簡潔。

type HandlerFunc func(ResponseWriter, *Request)

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

先ほどのHandleFuncも、実際は中でHandlerFuncを読んで変換している、と言う感じ。

func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {

mux.Handle(pattern, HandlerFunc(handler))
}

次は @hajimehoshi さんです