ルーティング
パスごとに処理を分ける
エンドポイントが増えると、ハンドラを1つずつ登録します。この登録を受け持つのが ServeMux です。
Go
mux := http.NewServeMux()
mux.HandleFunc("/health", healthHandler)
mux.HandleFunc("/items", itemsHandler)
http.ListenAndServe(":8080", mux)mux は multiplexer(振り分け役)の略です。届いたリクエストのパスを見て、対応するハンドラへ渡します。
前方一致に注意
Go
mux.HandleFunc("/items", itemsHandler) // /items だけ
mux.HandleFunc("/items/", itemsHandler) // /items/ で始まる全部末尾のスラッシュで意味が変わります。 付けると前方一致になり、/items/1 も /items/abc/def も同じハンドラに届きます。
詳細ページを作るときはこれを使います。/items/1 の 1 は自分で取り出します。
メソッドつきで登録できる
Go 1.22 から、メソッドとパスパラメータをまとめて書けるようになりました。
Go
mux.HandleFunc("GET /items", listHandler)
mux.HandleFunc("POST /items", createHandler)
mux.HandleFunc("GET /items/{id}", detailHandler){id} の部分は、ハンドラの中で取り出せます。
Go
id := r.PathValue("id")これが入るまでは、パスを自分で切り分けるか、外部のライブラリを使うのが普通でした。標準ライブラリだけで書ける範囲が広がった変更です。
このコースでは前者の書き方も扱います。 実務のコードにはどちらも残っているためです。
登録されていないパス
ServeMux は、どれにも当てはまらないパスに自動で 404 を返します。自分で書く必要はありません。
プレーンテキスト
GET /unknown → 404 page not found本文が page not found という決まった文言になります。JSON を返す API では、この既定の応答が混ざると扱いにくいので、後のレッスンで自分の形に揃えます。
このコースでの確かめ方
httptest では mux を直接呼べます。
Go
mux := http.NewServeMux()
mux.HandleFunc("/health", healthHandler)
req := httptest.NewRequest("GET", "/health", nil)
rec := httptest.NewRecorder()
mux.ServeHTTP(rec, req)ハンドラを直接呼ぶ代わりに mux.ServeHTTP を呼びます。振り分けまで含めて試せるので、パスの登録が正しいかも確かめられます。
要件
http.NewServeMux()で mux を作る/health/items/versionの3つを登録する- それぞれ
okitems1.0.0を返す - 登録していないパスは ServeMux に任せる
入出力例
callRoute("/health") → "200 ok"
callRoute("/items") → "200 items"
callRoute("/version") → "200 1.0.0"
callRoute("/unknown") → "404"ヒント
編集 ゆめさく編集部