Overview
go-cmp を使って実際取得した値と期待値を比較するときに go-cmp/cmpopts を使って、二値の比較のオプションを設定することが出来ますが、この二値が map のときに map の中の特定の key に紐づく value のみを比較したいというユースケースがあって、既存の options だけでは満たせなかったのでやり方を考えました。
cmpopts.IgnoreMapEntries を利用する
IgnoreMapEntries を利用します。
IgnoreMapEntries
は map 同士を比較、もしくは map と比較するときに特定の key-value のセットを ignore するという options になります。
discardFunc
は interface を取っていますが、ここは func(k string, v any) bool
という func 型を取り、指定した key を指定して返り値が true となる key-value のセットを ignore します。
繰り返しですが、このメソッドは func(k string, v any) bool
の返り値が true のときの key-value のセットを ignore する、というオプションになるので、逆に false の場合は Ignore しない(=残る)というものになります。そのため、以下のようなメソッドを用意して特定の key-value のセットのみを残す(= フィルタする)ということが可能です。
// any のところは比較したい map の型定義に合わせる。例えば map[string]int 同士を比較したい場合は `want map[string]int` をとります。 func FilterWantMapEntires(want map[string]any) cmp.Option { return cmpopts.IgnoreMapEntries(func(k string, _ any) bool { _, ok := want[k] return !ok }) }
使い方としては以下のような感じで option の中に組み込むことを想定しています。
func main() { got := map[string]int{"1": 1, "2": 2, "3": 3} want := map[string]int{"1": 1, "2": 2} // 1 と 2 のみ比較したい。 opts := []cmp.Option{ FilterWantMapEntries(want), } if diff := cmp.Diff(got, want, opts...); diff != "" { fmt.Println(diff) } }
ref: https://go.dev/play/p/4eU9w2nTgBp
Ref
あとから調べたのですが、go-cmp の cmpopts の使い方で実際にユースケースでよく使うものをベースに以下がよくまとまっていました。