5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ラクスAdvent Calendar 2024

Day 7

GoのHTTPサーバー入門

Last updated at Posted at 2024-12-06

GoのHTTPサーバーのいろいろなパターンについて紹介します。

コード:https://github.com/tkeshun/http-server-explain

基本的なHTTPサーバー

パスに対応した処理が行われるように関数を登録します。
以下例では"http://<ホスト名>:8080/"にアクセスしたとき紐付けられた関数が実行されます。
関数はHandleFuncの引数に定義されたfunc(ResponseWriter, *Request)型にマッチすれば引数として渡すことができます。

package main

import (
	"fmt"
	"net/http"
)

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

func main() {
	http.HandleFunc("/", handler) // DefaultServeMuxにパスと対応する処理が登録される
	http.ListenAndServe(":8080", nil)
}

ライブラリのHTTPリクエストマルチプレクサを使ってHTTPサーバーを組み立てる方法

前項のコードの場合、何も指定していないため、DefaultServMuxというHTTPリクエストマルチプレクサが使用されている。

HTTPリクエストマルチプレクサは自分で変数宣言して使うことが可能である。

http.NewServeMux()で新たなマルチプレクサを作れる。

package main

import (
	"fmt"
	"net/http"
)

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

func main() {
	mux := http.NewServeMux()
	mux.HandleFunc("/", handler)
	// マルチプレクサ(handler)を登録する必要がある
	// 登録する場合、第一引数のポート番号と第2引数のhandlerがServer構造体に登録された上で、ServerのListenAndServeメソッドが実行される
	http.ListenAndServe(":8080", mux)
}

Handlerを自分で実装するパターン

今までのコードでは、予め内部で実装済みのServeHTTPメソッドが呼び出されていた。
http.Handlerインターフェースを実装した構造体を用意することで、中身の処理を自身で記述できるようになる
以下の例では、 フィールドなしの構造体を定義して、ServeHTTPメソッドを実装している。
http.Handle()はhttp.Handlerインターフェースを満たす構造体を要求するので、ServeHTTPを実装し、http.Handlerインターフェースを満たすことで引数に渡すことができるようになる。
カスタムハンドラーはこのあと紹介するミドルウェアパターンで役に立つ。

package main

import "net/http"

type CustomHandler struct{} // anyだとエラーになる

// http.Handlerのインターフェースを実装する
func (h *CustomHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("Custom handler\n"))
}

func main() {
	handler := &CustomHandler{}
	// DefaultServeMuxにカスタムハンドラーを登録する
	http.Handle("/", handler)
	http.ListenAndServe(":8080", nil)
}

ミドルウェアパターン

http.Handlerをラップすることで、ラップされるハンドラーの前後に処理を追加することができる 入れ子に組み合わせることで複数のミドルウェアを組み合わせられる。
これをミドルウェアパターンという。
ここでは、middlewareでhttp.Handlerをラップしている。
関数の中でnext.ServeHTTP(w, r)を呼び出すことで、本来実行されるはずだったServeHTTP関数を実行しつつ、引数のハンドラーが実行される前後に処理を挿むことができる。

以下が処理の流れの図。

middle.drawio.png

package main

import (
	"fmt"
	"net/http"
)

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

func middleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Println("ラップする処理の前に実行される")
		next.ServeHTTP(w, r)
		fmt.Println("ラップする処理の後に実行される")
	})
}

func main() {
	mux := http.NewServeMux()
	mux.HandleFunc("/", handler)
	mux.Handle("/middleware", middleware(http.HandlerFunc(handler)))

	// マルチプレクサ(handler)を登録する必要がある
	// 登録する場合、第一引数のポート番号と第2引数のhandlerがServer構造体に登録された上で、ServerのListenAndServeメソッドが実行される
	http.ListenAndServe(":8080", mux)
}

まとめ

GoのWebサーバーの使い方の基本を紹介した。
リポジトリにある他の使い方もそのうち紹介する。

5
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
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?