Go 1.6 で HTTP Request Context

Go 1.6(for Google App Engine)で、Go 1.7 の HTTP Request Context のような事をするメモ。

golang.org/x/net/context だけでいけるかな〜と思ったけど、そんなわけなくて、ゴリラ系のフレームワークを使った。

フレームワーク

なるべく簡素にしたいし、http.Handler をそのまま使いたかったので、以下を選択。

gorilla/contextHTTP Request Context の代替です。
リクエストオブジェクトをキーにして値をグローバルな変数に保管する的なことをしている。

自前のミドルウェアを用意して、リクエスト毎に値を保つコードを書くとこんな感じ。

import (
    ...
    "github.com/gorilla/context"
)

...

func MyMiddleware(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
    bag := &ExampleBag{}
    context.Set(req, "contextKey", bag) // http.Request毎に保管する
    next(w, req) // MyHandler 呼び出し
    context.Delete(req, "contextKey")
}

...

func MyHandler(w http.ResponseWriter, req *http.Request) {
    bag, ok := context.Get(req, "contextKey").(*ExampleBag)
    ...
}

Go 1.7 > では

func MyMiddleware(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
    bag := &ExampleBag{}
    ctx := context.WithValue(req.Context(), "contextKey", bag) // req.Context 便利
    next(w, req.WithContext(ctx))
}

...

func MyHandler(w http.ResponseWriter, req *http.Request) {
    bag, ok = req.Context().Value("contextKey").(*ExampleBag)
    ...
}

番外

Go 1.7 になったら、下記フレームワークに置き換えたい