いささか、旧聞に属しますが、今年の初めに出た Go1.22 で HTTP サーバーのルーティングに使われる net/http.ServeMux の機能が強化されて、HTTPメソッドの指定ができるようになり、かつ URL パターン文字列にワイルドカードが使えるようになりました。例として、次のような書き方ができるようになりました。
mux := http.NewServeMux()
mux.HandleFunc("GET /test/{id}", Test)
...
このように書くと、handler
側で Request.PathValue
メソッドを使うことにより {id}
の値を取得できるようになりました。
func Test(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
fmt.Printf("id = %s\n", id) // {id} の値が表示される
...
使えそうな機能強化ですが、ふと、疑問が頭に浮かびまして、
mux.HandleFunc("GET /test/{id}.dat", Test)
と、ワイルドカードの後に拡張子を付けて書いてみたらどうなるのだろう、と。
で、実際に書いてテストしてみました。Go のバージョンは 1.22.0
です。
結果は panic
でした。
panic: parsing "GET /test/{id}.dat": at offset 10: bad wildcard segment (must end with '}')
「最後が }
で終わらないとダメだ」と言ってます。
じゃあ、拡張子の部分もワイルドカードにして
mux.HandleFunc("GET /test/{id}{suffix}", Test)
としてみたらどうか?
これもパニック。
panic: parsing "GET /test/{id}{suffix}": at offset 10: bad wildcard name "id}{suffix"
「ワイルドカードの名前として id}{suffix
はダメだ」と言ってます。
よくわからないので、おとなしく Go 1.22 のリリースノートの該当部分 を読んでみました。
Wildcards in patterns, like /items/{id}, match segments of the URL path.
訳すと「/items/{id} などのパターン内のワイルドカードは、URL パスのセグメントと一致します」だそう。一つのセグメント全体を一つのワイルドカードにしなければいけない、ということのようです。
じゃあ、2つのセグメントにそれぞれワイルドカードを割り当てたら?
mux.HandleFunc("GET /test/{group}/{id}", Test)
これはいけました。
group
も id
も Request.PathValue
で値を取得できました。
ふ〜む・・・、これでいいのかな?