Goの構造体の比較の方法についてメモ
結論
go-cmp便利
シンプルな比較であればassert.Equalで十分。
ちょっと複雑なことをやるならgo-cmpを使うとよい。
例えば以下はよくあるケースだと思う。
- 日付など特定のカラムを除外して比較したい
- 構造体の配列の比較の際に並び順は無視して比較したい
調べた経緯
比較するのはいくつか方法があるのでどれが良いのか気になったため。
-
ObjectsAreEqual
https://pkg.go.dev/github.com/stretchr/testify/assert#ObjectsAreEqual -
assert.Equal(内部でObjectsAreEqualを呼びだしている)
https://pkg.go.dev/github.com/stretchr/testify/assert#Equal -
DeepEqual
https://pkg.go.dev/reflect#DeepEqual -
go-cmp
https://pkg.go.dev/github.com/google/go-cmp/cmp
https://pkg.go.dev/github.com/google/go-cmp@v0.6.0/cmp/cmpopts#IgnoreFields
go-cmp使い方例
- 比較時に配列の場合に並び順を気にせず、比較したい
- 特定のカラムを比較対象外にしたい
以下は結果はokとなる
package xxxx
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
)
func Test_xxxx(t *testing.T) {
type StructA struct {
ID int
Name string
CreatedAt time.Time
}
expected := []StructA{
{
ID: 1,
Name: "A",
CreatedAt: time.Now(),
},
{
ID: 2,
Name: "B",
CreatedAt: time.Now(),
},
}
result := []StructA{
{
ID: 2,
Name: "B",
CreatedAt: time.Now(),
},
{
ID: 1,
Name: "A",
CreatedAt: time.Now(),
},
}
// 比較時は並び順は考慮しない・created_atは比較対象外にする
opt := cmp.Options{
cmpopts.SortSlices(func(a, b StructA) bool {
return a.ID < b.ID
}),
cmpopts.IgnoreFields(StructA{}, "CreatedAt"),
}
// オプション(opt)を用いて比較
diff := cmp.Diff(expected, result, opt)
if diff != "" {
t.Errorf("(-expected, +result)\n%s", diff)
}