diff --git a/repr.go b/repr.go index dafa0ac..f3f6d82 100644 --- a/repr.go +++ b/repr.go @@ -299,8 +299,18 @@ func (p *Printer) reprValue(seen map[reflect.Value]bool, v reflect.Value, indent continue } - if p.omitZero && ((ft.Implements(isZeroerType) && f.CanInterface() && f.Interface().(isZeroer).IsZero()) || f.IsZero()) { - continue + if p.omitZero { + // check if this type is a nil pointer to a type implementing IsZero + // with a value receiver and, if so, avoid calling IsZero() on it as + // the method call will automatically dereference the nil pointer and + // panic. + var nilPtrValueReceiver bool + if ft.Kind() == reflect.Pointer && f.IsNil() { + _, nilPtrValueReceiver = ft.Elem().MethodByName("IsZero") + } + if (ft.Implements(isZeroerType) && !nilPtrValueReceiver && f.CanInterface() && f.Interface().(isZeroer).IsZero()) || f.IsZero() { + continue + } } if p.omitEmpty && (f.IsZero() || diff --git a/repr_test.go b/repr_test.go index a4fd1f8..7ead252 100644 --- a/repr_test.go +++ b/repr_test.go @@ -81,8 +81,9 @@ func TestReprZeroSliceMapFields(t *testing.T) { B bool ZC zeroTest C zeroTest - }{[]string{}, []string{"a", "b"}, map[string]string{}, map[string]string{"a": "b"}, 0, 1, "", "a", false, true, zeroTest{i: 100}, zeroTest{i: 10}} - equal(t, `struct { ZSl []string; Sl []string; ZM map[string]string; M map[string]string; ZI int; I int; ZS string; S string; ZB bool; B bool; ZC repr.zeroTest; C repr.zeroTest }{ZSl: []string{}, Sl: []string{"a", "b"}, ZM: map[string]string{}, M: map[string]string{"a": "b"}, I: 1, S: "a", B: true, C: repr.zeroTest{i: 10}}`, String(v, OmitEmpty(false), OmitZero(true))) + T *time.Time + }{[]string{}, []string{"a", "b"}, map[string]string{}, map[string]string{"a": "b"}, 0, 1, "", "a", false, true, zeroTest{i: 100}, zeroTest{i: 10}, nil} + equal(t, `struct { ZSl []string; Sl []string; ZM map[string]string; M map[string]string; ZI int; I int; ZS string; S string; ZB bool; B bool; ZC repr.zeroTest; C repr.zeroTest; T *time.Time }{ZSl: []string{}, Sl: []string{"a", "b"}, ZM: map[string]string{}, M: map[string]string{"a": "b"}, I: 1, S: "a", B: true, C: repr.zeroTest{i: 10}}`, String(v, OmitEmpty(false), OmitZero(true))) } func TestReprStringArray(t *testing.T) {