Golang 用 URL ルーター Denco をリリースしました。
ちょっと前までは最速でしたが、HttpRouter の作者によって高速にバックミラーから消し去られました。
ですが、HttpRouter ではできないことが Denco にできたりしますしおすし。
ベンチマークは https://github.com/julienschmidt/go-http-routing-benchmark からどうぞ。
Denco とは
既に開発していた kocha-urlrouter のダブル配列実装をベースに色々と手を加えたものになります。
速度を重視して開発してましたが、前述の通り HttpRouter に追いぬかれました。
使い方
下記のように使います。
router := denco.New()
router.Build([]denco.Record{
{"/", "root"},
{"/user/:id", 1024},
{"/user/:name/:id", []string{"username"}},
{"/static/*filepath", "static"},
})
data, params, found := router.Lookup("/")
fmt.Printf("%v\n", data.(string))
data, params, found = router.Lookup("/user/1")
fmt.Printf("%v, %v = %v\n", data.(int), params[0].Name, params[0].Value)
data, params, found = router.Lookup("/user/naoina/2")
fmt.Printf("%v\n", data.([]string))
for _, v := range params {
fmt.Printf("%v = %v\n", v.Name, v.Value)
}
data, params, found = router.Lookup("/static/path/to/other")
fmt.Printf("%v, %v = %v\n", data, params[0].Name, params[0].Value)
README にも書いてあるんですが、Go の http.ServeMux を置き換えるものではないので、http.Handler インターフェースは提供していません。
ですので、HandlerFunc などを呼ぶためのグルーコードを書く必要があります。
package main
import (
"fmt"
"log"
"net/http"
"github.com/naoina/denco"
)
type handler struct {
router *denco.Router
}
type handlerFunc func(http.ResponseWriter, *http.Request, []denco.Param)
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
m, params, found := h.router.Lookup(r.RequestURI)
if !found {
panic("route not found")
}
m.(handlerFunc)(w, r, params)
}
func Index(w http.ResponseWriter, r *http.Request, _ []denco.Param) {
fmt.Fprint(w, "Welcome!\n")
}
func Hello(w http.ResponseWriter, r *http.Request, params []denco.Param) {
fmt.Fprintf(w, "hello, %s!\n", params)
}
func main() {
router := denco.New()
if err := router.Build([]denco.Record{
{"/", handlerFunc(Index)},
{"/hello/naoina", handlerFunc(Hello)},
{"/hello/:name", handlerFunc(Hello)},
}); err != nil {
panic(err)
}
h := &handler{router}
log.Fatal(http.ListenAndServe(":8080", h))
}
これはそもそも Kocha で使うために書き始めたものなので上記のようになっています。
vs HttpRouter
再び最速の座を手に入れるべく頑張っていますが、現状では HttpRouter とほぼダブルスコアです。。。社会は厳しい!
ですが、Denco にしかできないことがあります。
例えば、HttpRouter では /user/:name
と /user/naoina
など、パラメーター付きパスと静的パスがかぶるようなルートが一緒に使えず、構築時に panic するようになっていますが、Denco だと問題ありません。
router.Build([]denco.Record{
{"/user/:name", "first"},
{"/user/naoina", "second"},
})
router.Lookup("/user/hoge") // "first"
router.Lookup("/user/foo") // "first"
router.Lookup("/user/naoina") // "second"
まぁ、負け惜しみです。
まとめ
私が調べた限りだと、ダブル配列を使った URL ルーターの実装というものがありませんでした。
ですので、参考になるか分かりませんが、次回から Denco の技術解説みたいなのを書こうかなと考えています。