LoginSignup
0
0

More than 1 year has passed since last update.

HandleFuncとHandleでは何が起きてる?違いは?

Last updated at Posted at 2021-09-13

HandleFuncHandleの実行部分

注)実行したい関数、オブジェクトをhelloHandlerとする。

HandleFuncの実行部分

http.HandleFunc("/hello", helloHandler)

Handleの実行部分

http.Handle("/hello", &helloHandler{})

とても似ている!!!
なにが違うの??

HandleFuncHandleの違い

どちらも第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を自分で実装する。
そうするとhelloHandlerServeHTTPメソッドを実装しているため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に登録される。

HandleFuncHandleの実装例

最後にHandleFuncHandleの実装例を見てみる。

注)実行したい関数、オブジェクトを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型HandlerServeHTTPという関数を定義したインターフェイス)を作る。
実行では、http.HandleにはURLとhttp.Handlerインタフェースを実装したオブジェクト(helloHandler)を引数として渡す。

参考文献

Go言語の公式ドキュメント 「http.Handler」
Go言語の公式ドキュメント 「http.HandleFunc」
Go言語の公式ドキュメント 「http.Handle」

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0