Go言語学習(net/http における HTTP サーバー構築)

net/http パッケージは http クライアント、サーバーとしての役割に必要な処理を集めたパッケージ。

今回はサーバーとしての使い方を学んだ。

最小構成

最小構成といいつつ待受アドレスは変更している。第一引数は何も設定しなければ :80 で待受する。 このコードの場合、「ハンドラ」が渡されていないので 404 not found になる。

package main

import "net/http"

func main () {
	// 第一引数は待受するアドレス。
	// 第荷引数はハンドラ
	http.ListenAndServe("127.0.0.1:8080", nil)
}

http.Server 構造体

http.Server 構造体からインスタンスを生成する際にサーバーの設定値をいじる。 上記例をそのまま http.Server 構造体インスタンスで書き換えるとこうなる。

server := http.Server {
	Addr: "127.0.0.1:8080"
	Handler: nil
}

ハンドラ

  • ハンドラ: ServeHTTP メソッドを持つインターフェースを指す
  • ハンドラ関数: ハンドラのように振る舞う関数。後述するが、ハンドラを毎回インスタンス化するのは大変なので、ハンドラのように扱える関数を定義することで簡略化できる。

HelloHandler というエイリアスを持つ空構造体に対して ServeHTTP メソッドを実装し、 handler := MyHandler{} でインスタンス化してそいつを http.ServerHandler に割り当てる

type HelloHandler struct {}

func (h *HelloHandler ) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello World!")
}

func main () {
	handler := HelloHandler{}
	server := http.Server {
		Addr: "127.0.0.1:8080",
		Handler: &handler,

	}
	server.ListenAndServe()
}

複数のパスをハンドラで処理する

type HelloHandler struct {}

func (h *HelloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello!")
}

type WorldHandler struct {}

func (h *WorldHandler) ServeHTTP(w http.ResponseWriter, r *http.Request){
	fmt.Fprintf(w, "World!")
}

func main () {
	fmt.Println("HTTP srerver is running")
	hello := HelloHandler{}
	world := WorldHandler{}

	server := http.Server {
		Addr: "127.0.0.1:8080",

	}
	http.Handle("/hello", &hello)
	http.Handle("/world", &world)

	server.ListenAndServe()
}

ハンドラ関数

ハンドラ関数は、 ServeHTTP と同じ引数 (http.ResponseWriter, r *http.Request) を取る関数。 ハンドラは ServeHTTPメソッドを持つインスタンスなので、ハンドラでリクエストを処理するときは必ず実体化しなければいけない。

ハンドラ関数であれば、 http.HandleFunc の引数に処理するパスと、作成した関数を渡すことで同じことができる。

複数のパスをハンドラ関数で処理する

func hello(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello! HandlerFunc~")
}

func world(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "World! HandlerFunc~")
}

func main () {
	fmt.Println("HTTP srerver is running")

	server := http.Server {
		Addr: "127.0.0.1:8080",

	}

	// HandleFunc 関数は HandlerFunc 型を第2引数に取る。
	// HandlerFunc 型の関数は http.ResponseWriter, *http.Request を引数に持つ関数である。
	http.HandleFunc("/hello", hello)
	http.HandleFunc("/world", world)

	server.ListenAndServe()
}

参考