goji.ioで正規表現Pattern
ハンドラのとこはgoji.ioで書いてます。見ると標準のnet/httpとgolang.org/x/net/contextをうまいこと活かしたからこその極薄なライブラリなのですが、リクエストパスでハンドラを切り替えるのに簡潔利便なので私はお好みです。しかし薄すぎて足りないところもあったのでパス切り替え判断のところ、ちょこっと補ってみました。
package patx import ( "regexp" "net/http" "golang.org/x/net/context" ) type RegexpPattern struct { regexp *regexp.Regexp } func Regexp(expr string) *RegexpPattern { // MustCompileだと渡された表現文字列がコンパイルエラーのときpanicで止める。よろしい。 return &RegexpPattern{regexp: regexp.MustCompile(expr)} } // goji.Patternインターフェイスを実装している func (reg *RegexpPattern) Match(ctx context.Context, r *http.Request) context.Context { if reg.regexp.MatchString(r.URL.Path) { // 手抜きでMatchStringでの当り判定だけなので、積むものがなく、よってctxに何も積んでない。 return ctx; } return nil }
たったのこれだけで、とてつもなく手がかかってない実装ですが、そうはどっこい意外に便利。正規表現で書きたいこともある。
package main import ( "book" "goji.io" "goji.io/pat" "net/http" "patx" ) func main() { mux := goji.NewMux() // 拡張子6種を簡単な正規表現でマッチさせてhttp.FileServerへルーティングする mux.Handle( patx.Regexp(`(.*\.(css|ttf|gif|png|jpg|js))$`), http.FileServer(http.Dir("public")) ) mux.HandleFuncC(pat.Get("/book/list"), book.ListBookJSON) mux.HandleFuncC(pat.Get("/book/:title"), book.ListPageJSON) // こっから先はGoは静的HTML出すだけで、reactアプリになる mux.HandleFuncC(pat.Get("/*"), book.IndexHTML) http.ListenAndServe("localhost:8080", mux) }
こんな感じです。GAEだと、こんな取り込みはいらず、yamlファイルに正規表現書いて同じことができますけど、平場のGOだと自分で書く。
なんで平場のGoで書かないといけないのか
GAE/GoのSDKでSierra対応版がまだ出てこないから。仮想でやるのは重いので緊急避難。GAE機能つかってるところはダメでも、そこらへんだけ殺してモック的に動かしておいて、当面はクライアントのところだけを書いてましょう。
後に気がつきましたが、macOS 10.12.1+go1.7.3 darwin/amd64環境下でGoのデバッガが「could not launch process: could not get thread count」と吐いてクラッシュしてしまいます。インクリメンタルデバッグはできない。実行はできるので、その延長線にてユニットテストはできる。
Goの正規表現
Syntax · google/re2 Wiki · GitHub
こちらの仕様とのことらしく。named captureができないなーと思ってたら、?P<name>が正解で?<name>は非サポートだった。。。