From 2b8252e0e2927def6d2e4b3da423773b7da0c593 Mon Sep 17 00:00:00 2001 From: Dennis Kaarsemaker Date: Tue, 14 Nov 2023 10:03:28 +0100 Subject: [PATCH] Add an option to consider nil pointers to be equivalent to zero values Similar to NilSlicesAreEmpty and NilStructsAreEmpty, this lets one consider nil pointers and zero values as equal. --- deep.go | 9 +++++++++ deep_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/deep.go b/deep.go index 4aab66a..4be3e1f 100644 --- a/deep.go +++ b/deep.go @@ -43,6 +43,9 @@ var ( // NilMapsAreEmpty causes a nil map to be equal to an empty map. NilMapsAreEmpty = false + + // NilPointersAreZero causes a nil pointer to be equal to a zero value. + NilPointersAreZero = false ) var ( @@ -190,6 +193,12 @@ func (c *cmp) equals(a, b reflect.Value, level int) { if bElem { b = b.Elem() } + if aElem && NilPointersAreZero && !a.IsValid() && b.IsValid() { + a = reflect.Zero(b.Type()) + } + if bElem && NilPointersAreZero && !b.IsValid() && a.IsValid() { + b = reflect.Zero(a.Type()) + } c.equals(a, b, level+1) return } diff --git a/deep_test.go b/deep_test.go index 0cc96cf..77c8b82 100644 --- a/deep_test.go +++ b/deep_test.go @@ -1581,3 +1581,27 @@ func TestSliceOrderStruct(t *testing.T) { t.Fatalf("expected 0 diff, got %d: %s", len(diff), diff) } } + +func TestNilPointersAreZero(t *testing.T) { + defaultNilPointersAreZero := deep.NilPointersAreZero + deep.NilPointersAreZero = true + defer func() { deep.NilPointersAreZero = defaultNilPointersAreZero }() + + type T struct { + S *string + } + + a := T{S: nil} + b := T{S: new(string)} + + diff := deep.Equal(a, b) + if len(diff) != 0 { + t.Fatalf("expected 0 diff, got %d: %s", len(diff), diff) + } + + *b.S = "hello" + diff = deep.Equal(a, b) + if len(diff) != 1 { + t.Fatalf("expected 1 diff, got %d: %s", len(diff), diff) + } +}