diff --git a/repr.go b/repr.go index 7e3b5ad..56a2489 100644 --- a/repr.go +++ b/repr.go @@ -105,6 +105,13 @@ func Hide[T any]() Option { } } +// HideField excludes fields of structs that match the given name from representation. +func HideField(name string) Option { + return func(o *Printer) { + o.excludeFields[name] = true + } +} + // AlwaysIncludeType always includes explicit type information for each item. func AlwaysIncludeType() Option { return func(o *Printer) { o.alwaysIncludeType = true } } @@ -118,6 +125,7 @@ type Printer struct { alwaysIncludeType bool explicitTypes bool exclude map[reflect.Type]bool + excludeFields map[string]bool w io.Writer useLiterals bool } @@ -125,11 +133,12 @@ type Printer struct { // New creates a new Printer on w with the given Options. func New(w io.Writer, options ...Option) *Printer { p := &Printer{ - w: w, - indent: " ", - omitEmpty: true, - omitZero: true, - exclude: map[reflect.Type]bool{}, + w: w, + indent: " ", + omitEmpty: true, + omitZero: true, + exclude: map[reflect.Type]bool{}, + excludeFields: map[string]bool{}, } for _, option := range options { option(p) @@ -280,6 +289,9 @@ func (p *Printer) reprValue(seen map[reflect.Value]bool, v reflect.Value, indent if p.exclude[t.Type] { continue } + if p.excludeFields[t.Name] { + continue + } f := v.Field(i) ft := f.Type() // skip private fields diff --git a/repr_test.go b/repr_test.go index 752a515..a4fd1f8 100644 --- a/repr_test.go +++ b/repr_test.go @@ -278,7 +278,7 @@ func TestReprPrivateBytes(t *testing.T) { } func TestReprAnyNumeric(t *testing.T) { - var value = []any{float64(123)} + value := []any{float64(123)} equal(t, "[]any{float64(123)}", String(value)) } @@ -293,3 +293,12 @@ func TestScalarLiterals(t *testing.T) { d := time.Second equal(t, "time.Duration(1000000000)", String(d, ScalarLiterals())) } + +func TestHideStructFieldsByName(t *testing.T) { + actual := testStruct{ + S: "str", + A: anotherStruct{A: []int{1}}, + } + res := String(actual, HideField("A")) + equal(t, `repr.testStruct{S: "str"}`, res) +}