https://blog.gainings.dev/posts/go_deepequal_trap/
この記事は 2018年 アドベントカレンダーとなんの関係もない記事です.
どうも一回も怒られたことがないバイトリーダーのゲインです.
さて本日バイトでModel周りのテストコードを書いていた時に reflect.DeepEqual
でガッツリハマったので,共有しておきたいと思います.
さて皆さんこちらのコードを御覧ください. playgroundはこちら
このコードの実行結果はどうなるでしょう. 実行せずに考えてみてください.
package main
import (
"encoding/json"
"fmt"
"log"
"reflect"
)
type Hoge struct {
Hoge string `json:"hoge"`
Huga int `json:"huga"`
}
func main() {
m1 := make(map[string]interface{}, 0)
m1["hoge"] = "hogehoge"
m1["huga"] = 1
m2 := make(map[string]interface{}, 0)
m2["hoge"] = "hogehoge"
m2["huga"] = 1
hoge := Hoge{
Hoge: "hogehoge",
Huga: 1,
}
hogeJSON, err := json.Marshal(hoge)
if err != nil {
log.Fatal(err)
}
var m3 map[string]interface{}
err = json.Unmarshal(hogeJSON, &m3)
if err != nil {
log.Fatal(err)
}
fmt.Printf("m1 == m2?: %t\\n", reflect.DeepEqual(m1, m2))
fmt.Printf("m1 == m3?: %t\\n", reflect.DeepEqual(m1, m3))
fmt.Printf("m2 == m3?: %t\\n", reflect.DeepEqual(m2, m3))
}
中身としてはm1,m2は同じキーに対して同じ値を入れた別の変数.
m3に関しては構造体を一度JSONにしてから map[string]interface{}
にUnmarshalした変数になってます.
さてこれを実行すると以下のように表示されるでいいですか?
m1==m2?: true
m1==m3?: true
m2==m3?: true
…残念ながら違うんです.
午前中の私は上記になると思ってました.
実際はこうです.
m1 == m2?: true
m1 == m3?: false
m2 == m3?: false
さてどうしてこんなことになるんでしょう.
中身を確認してみましょう