diff --git a/diff.go b/diff.go index 6aa7f74..808af32 100644 --- a/diff.go +++ b/diff.go @@ -37,6 +37,11 @@ type Printfer interface { Printf(format string, a ...interface{}) } +// Diffable is the interface that gives a chance to return custom value for diff +type Diffable interface { + DiffValue() interface{} +} + // Pdiff prints to p a description of the differences between a and b. // It calls Printf once for each difference, with no trailing newline. // The standard library log.Logger is a Printfer. @@ -77,6 +82,17 @@ func (w diffPrinter) printf(f string, a ...interface{}) { } func (w diffPrinter) diff(av, bv reflect.Value) { + if av.IsValid() && av.CanInterface() { + if diffable, ok := av.Interface().(Diffable); ok { + av = reflect.ValueOf(diffable.DiffValue()) + } + } + if bv.IsValid() && bv.CanInterface() { + if diffable, ok := bv.Interface().(Diffable); ok { + bv = reflect.ValueOf(diffable.DiffValue()) + } + } + if !av.IsValid() && bv.IsValid() { w.printf("nil != %# v", formatter{v: bv, quote: true}) return diff --git a/diff_test.go b/diff_test.go index a951e4b..366abb2 100644 --- a/diff_test.go +++ b/diff_test.go @@ -31,8 +31,13 @@ type S struct { type ( N struct{ N int } E interface{} + D struct{ a string } ) +func (d D) DiffValue() interface{} { + return d.a +} + var ( c0 = make(chan int) c1 = make(chan int) @@ -59,6 +64,8 @@ var diffs = []difftest{ {S{C: []int{}}, S{C: []int{1}}, []string{`C: []int[0] != []int[1]`}}, {S{C: []int{1, 2, 3}}, S{C: []int{1, 2, 4}}, []string{`C[2]: 3 != 4`}}, {S{}, S{A: 1, S: new(S)}, []string{`A: 0 != 1`, `S: nil != &pretty.S{}`}}, + {D{a: "a"}, D{a: "b"}, []string{`"a" != "b"`}}, + {struct{ D D }{D{"a"}}, struct{ D D }{D{"b"}}, []string{`D: "a" != "b"`}}, // unexported fields of every reflect.Kind (both equal and unequal) {struct{ x bool }{false}, struct{ x bool }{false}, nil},