Go 言語の http パッケージにある Handle とか Handler とか HandleFunc とか HandlerFunc とかよくわからないままとりあえずイディオムとして使ってたのでちゃんと理解したメモ

  • 21
    いいね
  • 0
    コメント

はじめに

  • 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 とは

  • http.Handle とは表示する URL と、URL に対応する http.HandlerDefaultServeMux に登録する関数です。
  • 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 とは

  • URL と func(ResponseWriter, *Request) を渡して DefaultServeMux に登録する関数です。
  • 内部で func(ResponseWriter, *Request) から http.HandlerFunc へのキャストが行われています。

さいごに

  • 全部ドキュメントに載っていて読めってはなしなのでドキュメント大切。
  • この記事は以下の記事からリンクされています
  • golangのお勉強2 からリンク