HandleFuncとHandleの実行部分
注)実行したい関数、オブジェクトをhelloHandlerとする。
HandleFuncの実行部分
http.HandleFunc("/hello", helloHandler)
Handleの実行部分
http.Handle("/hello", &helloHandler{})
とても似ている!!!
なにが違うの??
HandleFuncとHandleの違い
どちらも第1引数にはURLをとる。この二つには第2引数に違いがある。
HandleFunc
http.HandleFuncは、第2引数にhttp.ResponseWriterと*http.Requestを取る関数をそのまま渡せる。
Handle
HandleFunc関数とは違い、Handle関数の第2引数には関数を指定しない。HandleではhelloHandler型のServeHTTP関数を定義したHandlerのポインタを指定する。
つまり、http.Handleは、第2引数に***http.Handlerインタフェースを実装したオブジェクトを渡す。
ん?http.Handlerインタフェースを実装したオブジェクトって?
HandlerとはServeHTTPという関数*を定義したインターフェイスのこと。参考:Handlerの公式ドキュメント
つまり、第2引数はServeHTTP(http.ResponseWriter, *http.Request)という関数を実装したオブジェクトあれば良い。
func (t *helloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } のようにhelloHandler用にServeHTTPを自分で実装する。
そうするとhelloHandlerはServeHTTPメソッドを実装しているためhttp.Handlerインタフェースを実装したオブジェクトとなる。
これまでのことも含め、何が起きているのかを見てみる
HandleFunc
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
-公式ドキュメントより参照
第1引数ではURLのパターンを受け取り、第2引数ではURLで実行したい関数を受け取る。
そしてDefaultServeMux.HandleFuncに登録される。これはURLとHandlerの関連付けをおこなう役割を持つ。
DefaultServeMuxはグローバルなServeMuxのインスタンス。net/httpパッケージにおいてあらかじめDefaultServeMuxが用意されている。
つまり、HandleFuncでは引数にURLと関数を渡すことで、それら二つを関連づけたものを登録してくれる。そして、URLにアクセスすると登録したところから探し出し、関数を実行してくれる。
Handle
func Handle(pattern string, handler Handler){
DefaultServeMux.HandleFunc(pattern, handler)
}
-公式ドキュメントより参照
第1引数ではHandleFunc同様、URLのパターンを受け取る。第2引数ではURLで実行したい関数をServeHTTP関数に定義したHandlerのポインタを受け取る。
そしてDefaultServeMux.HandleFuncに登録される。
HandleFuncとHandleの実装例
最後にHandleFuncとHandleの実装例を見てみる。
注)実行したい関数、オブジェクトをhelloHandlerとする。
HandleFuncの実装例
package main
import (
"fmt"
"net/http"
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "<h1>Hello, World</h1>") //「/hello」URLで実行したい処理
}
func main() {
http.HandleFunc("/hello", helloHandler)
http.ListenAndServe(":8080", nil)
}
このようにURLで実行したい関数を作成し、実行ではHandFunc関数に引数としてURLと関数を渡す。
HandleFuncの実装例
package main
import (
"fmt"
"net/http"
)
type helloHandler struct{}
func (*helloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "<h1>Hello, World</h1>") //「/hello」URLで実行したい処理
}
func main() {
http.Handle("/hello", &helloHandler{})
http.ListenAndServe(":8080", nil)
}
まずオブジェクトを作成し、URLで処理したい関数をServeHTTP内に記述する。
このように、ServeHTTP関数を定義したhelloHandler型のHandler(ServeHTTPという関数を定義したインターフェイス)を作る。
実行では、http.HandleにはURLとhttp.Handlerインタフェースを実装したオブジェクト(helloHandler)を引数として渡す。
参考文献
Go言語の公式ドキュメント 「http.Handler」
Go言語の公式ドキュメント 「http.HandleFunc」
Go言語の公式ドキュメント 「http.Handle」