golangは総称型(Generics)がない、固い型の言語です。
そのため、javascriptやPythonなどと比較してネストの深いオブジェクトを扱うのが非常に面倒だと感じる事が多々あります。
そんなとき、Golangの先人は「筋力を使え」と言ったりしますね。(つまり我慢しろと)
状況
var a = `
{
"a": {
"b": {
"c": {
"d": 1
}
}
}
}
`
たとえばこんなjsonからdの値を取り出したいとします。
typesafeに扱うためには
var o map[string]map[string]map[string]map[string]int
json.Unmarshal([]byte(a), &o)
fmt.Println(o["a"]["b"]["c"]["d"])
とやったり
var o map[string]interface{}
json.Unmarshal([]byte(a), &o)
b,_ := o.a.(map[string]interface{})
c,_ := b.c.(map[string]interface{})
d,_ := c.d.(map[string]interface{})
fmt.Println(d)
とやるんでしょうかね。。。
また逆に、ネストの深いオブジェクトを作るときも同様なつらさがありますね。
ネストの深いオブジェクトから値を取り出す
var d interface{}
err := json.Unmarshal([]byte(a), &d)
d, err := jsonpath.Read(d, "$.a.b.c.d")
ここではjsonpathを使っていますが、この手のライブラリは様々な種類があると思います。
goでtypesafeにデータを扱うのがつらいときは、typelessに扱う事を検討してみては?
というのがここで言いたい事です。
ネストの深いオブジェクトを作る
逆のケースだとこんな風に書けます。
template.tpl
{
"a": {
"b": {
"c": {
"d": {{.Data}}
}
}
}
}
golang標準のtemplateを使用します。
tpl := template.Must(template.ParseFiles("template.tpl"))
var d = map[string]int{
"Data":1
}
tpl.Execute(w, d)
のようにしてしまうことで、データ構造を全てtypeとして表現することなく目的のobjectを作ってしまう事ができます。
結論
複雑なDDLを全て、typeとして定義する必要がない事は多々あると思います。そういうとき、
typelessにデータを扱う事により楽になることは多いのではないでしょうか。
もちろん処理速度などのデメリットはあるかもしれませんので、使用についてはメリデメを検討する必要があるとは思いますが。
「筋力!」と言ってくるGolangの先達はこういう方法をどう考えるんでしょうかね?