Open10

net/httpを紐解いてみる

あおあお

GoのHTTPサーバーを知るにはnet/httpパッケージの主要な型、インタフェースを押さえると見通しがよくなります。大きく以下の3つです。

  • Handlerインタフェース
  • HandlerFunc型
  • ServeMux型

※ オライリー・ジャパン『実用Go言語』10.2.1 HTTPサーバーを実装する より

あおあお

Handlerインタフェース

type Handler interface {
  ServeHTTP(ResponseWriter, *Request)
}

HandlerインタフェースはServeHTTPメソッドを定義しています。リクエストが呼び出されたときに動作するハンドラーです。Handlerインタフェースを満たしていれば、HTTPサーバーのハンドラーとしてふるまえます。

※ オライリー・ジャバン『実用Go言語』 10.2.1 HTTPサーバーを実装する より

なるほど、「Handlerインタフェースを満たす」ことがハンドラーとして振る舞うことの条件のようだ。

あおあお

ここで、「特定のインタフェースを満たす」ことを「特定のインタフェースを満たすメソッドを実装する」こととして、間違って理解している気がしてくる。

あおあお

Goのinterfaceについて今一度調べてみる

あおあお
  1. インタフェースとして定義した型で宣言したメソッドと同じシグネチャで任意の型をレシーバとするメソッドを実装
  2. 1にてメソッドを実装した任意の型をインターフェースとして定義した型に代入

1,2を通して、インターフェースの型に対して、メソッドが自動で実装される

あおあお

HandlerFunc型

type HandlerFunc func(w ResponseWriter, r *Request)
  • Goは構造体はもちろんのこと、関数型も型リテラルとして宣言することができる
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}
  • net/httpには上記に加えて、type HandlerFuncをレシーバとしてServeHTTP(wq ResponseWriter, r *Request)というシグネチャのメソッドがある
あおあお

そのため、関数リテラルfunc(w ResponseWriter, r *Request)

e.g)

func Hello(w ResponseWriter, r *Request) {
     w.Write([]byte("Hello"))
}

を作り、HandlerFuncでキャストすることで、

HandlerFunc(Hello)

Handlerインタフェースを満たすことができる

あおあお

ここで

ここで、「特定のインタフェースを満たす」ことを「特定のインタフェースを満たすメソッドを実装する」こととして、間違って理解している気がしてくる。

といったモヤモヤに立ち返る。

あおあお

「特定のインターフェースを満たすメソッドを実装する」ことを以下のような感じで理解していた

interfaceを満たすメソッドの実装例
package main

import "fmt"

type IFruits interface {
	Name() string
	Color() string
	Suger() int
	Sour() int
}

type Fluits struct {
	N  string
	C  string
	Su int
	So int
}

type Apple Fluits

func NewApple() IFruits {
	return Apple{
		N:  "Apple",
		C:  "Red",
		Su: 6,
		So: 5,
	}
}

func (a Apple) Name() string {
	return a.N
}
func (a Apple) Color() string {
	return a.C
}
func (a Apple) Suger() int {
	return a.Su
}
func (a Apple) Sour() int {
	return a.So
}

type Banana Fluits

func NewBanana() IFruits {
	return Banana{
		N:  "Banana",
		C:  "Yellow",
		Su: 9,
		So: 1,
	}
}

func (b Banana) Name() string {
	return b.N
}
func (b Banana) Color() string {
	return b.C
}
func (b Banana) Suger() int {
	return b.Su
}
func (b Banana) Sour() int {
	return b.So
}

type Orange Fluits

func NewOrange() IFruits {
	return Orange{
		N:  "Orrange",
		C:  "Orange",
		Su: 4,
		So: 7,
	}
}

func (o Orange) Name() string {
	return o.N
}

func (o Orange) Color() string {
	return o.C
}
func (o Orange) Suger() int {
	return o.Su
}
func (o Orange) Sour() int {
	return o.So
}

func main() {
	ap := NewApple()
	fmt.Println(ap.Color())
	ba := NewBanana()
	fmt.Println(ba.Suger())
	or := NewOrange()
	fmt.Println(or.Sour())
}
あおあお

ServeMux型

mux := http.NewServeMux()
mux.Handle
mux.HandlerFunc()
http.ListenAndServe(":8080", mux)