この記事はMakuake Advent Calendar 2023の19日目の記事です。
なんでこんな大遅刻かというと、唯一埋まっていなかった19日の枠を急遽埋めようと思って投稿したため。元々掴んでいた枠ではないので遅刻ではない。
去年くらいからGoのnet/httpに含まれるServeMuxの機能拡張の提案が出ていてウォッチしていたのだが、最近Closedになったらしい。
cf. net/http: enhanced ServeMux routing #61410 cf. GoでServeMuxの機能拡張を提案するProposalがAcceptedになった アプリケーション
この機能拡張はGo1.22に含まれる想定らしく、Go1.22rc2がリリースされたので試してみた。(Go1.22rc1から含まれているようだが、スルーしていた。)
tip.golang.org/doc/go1.22#net/httpに記載されている内容を見ると、以下のような変更点があるようだ。
ここを見た限りだとルーティングの仕様がどんな感じになったのかよくわからないので、ドキュメントの方を参照してみると色々書かれている。
cf. pkg.go.dev/net/http@go1.22rc2#ServeMux
Proposalの内容は全て追えていないのだが、Proposalで提案されていたルーティングのパターンマッチングの仕様がサードパーティのルーターのように充実した模様。
目立つところだけ端的にいうと、HTTPメソッド名やパスパラメータを使ったパターンマッチができるようになった感じ。
go.dev/dl - All releasesよりgo1.22rc2をダウンロードして触ってみる。
package main
import (
"net/http"
)
func main() {
mux := http.NewServeMux()
// HTTPメソッドがないパターンは全てのメソッドに一致する。
// {$}は特別なワイルドカードで、URLの末尾にのみ一致する。
// /{$}は/のみに一致するが、/は全てのパスに一致してしまう。
mux.HandleFunc("/{$}", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("/{$}"))
})
// GETメソッドはGETとHEADに一致する。
// {bar}はワイルドカード
mux.HandleFunc("GET /foo/{bar}", func(w http.ResponseWriter, r *http.Request) {
// パスパラメータの取得
v := r.PathValue("bar")
w.Write([]byte("GET /foo/" + v))
})
// {bar}はワイルドカード
mux.HandleFunc("POST /foo/{bar}", func(w http.ResponseWriter, r *http.Request) {
// パスパラメータの取得
v := r.PathValue("bar")
w.Write([]byte("POST /foo/" + v))
})
http.ListenAndServe(":8080", mux)
}
{$}やメソッドとルートを一緒に定義する形はサードパーティのルーターではあんまり見ないかもしれない。(自分が知らないだけかも...)
下位互換性については、pkg.go.dev/net/http@go1.22rc2#hdr-Compatibilityに記載されている。
Go1.21の仕様を引き継ぎたい場合は、httpmuuxgo121=1をGODEBUG環境変数に設定する必要があるとのこと。
自作ルーターであるgoblinはもはや使う必要がなくなってしまった気がするので、個人プロジェクトは新しいServeMuxを使っていくように切り替えていこうかと思う。
関連書籍