D3.jsの実験をするためにGoでREST APIサーバーもどきを書いたときのメモ

だいたいの可視化はRで事足りるけど、リアルタイムに更新される系のものをつくるときってどうするんだろう?と思って適当なダミーを書いてみたときのメモ(うまくいかなかったけど)。

サーバー側はGoで書いて、クライアント側はD3.jsっていうかMetricsGraphics.jsを使ってみる。

なんかEchoというやつが速いと聞いたので使ってみたけど、どうせそんなヘビーに使うわけじゃないし、Ginとか有名なやつを使えばよかったかも。もっと言えばRustlessを使ってRustを覚えるべきだったかも。

https://labstack.com/echo/

つまづいた点

Goのtime.Time型は、フォーマットを特に指定せず文字列に変換するとナノ秒精度のRFC3339形式(2016-02-28T13:50:00.9999999Z09:00みたいなの)になる一方で、d3.jsはISO 8601で(2016-02-28T13:50:00.999+0900みたいなの)、ミリ秒精度までなのとオフセット部分がうまくパースできない。

参考:Time Formatting · mbostock/d3 Wiki · GitHub

D3.js側はこれ以上フォーマットをいじれないっぽいので、Go側でどうにかするしかない。今回は文字列に変換する部分はjsonに任せてるので、MarshaleJSONUnmarshaleJSONを実装した新しい型が必要らしい。

参考:Guillaume's Thoughts: JSON Date management in Golang

type (
    myTime struct {
        time.Time
    }
    Record struct {
        Timestamp myTime `json:"timestamp"`
        Value     int    `json:"value"`
    }
)

func (t myTime) MarshalJSON() ([]byte, error) {
    return []byte(`"` + t.Time.Format("2006-01-02T15:04:05.999Z0700") + `"`), nil
}

Unmarshalは、今回は使わないのでサボる。

結果

MetricsGraphics.jsは値を更新するときにアニメーションが、こういうのを想定してない感じ。別のライブラリじゃないとだめっぽい...

f:id:yutannihilation:20160228131833g:plain