Skip to content

Commit 51334b8

Browse files
committed
feat: Add support to always show types.
Add support to always show types, even for built-in types such as `string`, `int`, `int32` etc. This will also show type for type aliases of such types.
1 parent c7f103e commit 51334b8

File tree

2 files changed

+94
-3
lines changed

2 files changed

+94
-3
lines changed

godump.go

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const (
3333
defaultMaxItems = 100
3434
defaultMaxStringLen = 100000
3535
defaultMaxStackDepth = 10
36+
defaultShowAllTypes = false
3637
initialCallerSkip = 2
3738
)
3839

@@ -84,6 +85,7 @@ type Dumper struct {
8485
maxDepth int
8586
maxItems int
8687
maxStringLen int
88+
showAllTypes bool
8789
writer io.Writer
8890
skippedStackFrames int
8991

@@ -149,13 +151,22 @@ func WithSkipStackFrames(n int) Option {
149151
}
150152
}
151153

154+
// WithShowAllTypes enables or disables always showing types for primitives.
155+
func WithShowAllTypes(b bool) Option {
156+
return func(d *Dumper) *Dumper {
157+
d.showAllTypes = b
158+
return d
159+
}
160+
}
161+
152162
// NewDumper creates a new Dumper with the given options applied.
153163
// Defaults are used for any setting not overridden.
154164
func NewDumper(opts ...Option) *Dumper {
155165
d := &Dumper{
156166
maxDepth: defaultMaxDepth,
157167
maxItems: defaultMaxItems,
158168
maxStringLen: defaultMaxStringLen,
169+
showAllTypes: defaultShowAllTypes,
159170
writer: os.Stdout,
160171
callerFn: runtime.Caller,
161172
}
@@ -469,7 +480,17 @@ func (d *Dumper) printValue(tw *tabwriter.Writer, v reflect.Value, indent int, v
469480
case reflect.UnsafePointer:
470481
fmt.Fprint(tw, colorize(colorGray, fmt.Sprintf("unsafe.Pointer(%#x)", v.Pointer())))
471482
case reflect.Map:
472-
fmt.Fprintln(tw, "{")
483+
if d.showAllTypes {
484+
keyType := v.Type().Key().Kind().String()
485+
valType := v.Type().Elem().Kind().String()
486+
keyValType := fmt.Sprintf("#map[%s]%s", keyType, valType)
487+
488+
fmt.Fprintf(tw, "{ %s", colorize(colorGray, keyValType))
489+
fmt.Fprintln(tw)
490+
} else {
491+
fmt.Fprintln(tw, "{")
492+
}
493+
473494
keys := v.MapKeys()
474495
for i, key := range keys {
475496
if i >= d.maxItems {
@@ -496,7 +517,13 @@ func (d *Dumper) printValue(tw *tabwriter.Writer, v reflect.Value, indent int, v
496517
}
497518

498519
// Default rendering for other slices/arrays
499-
fmt.Fprintln(tw, "[")
520+
if d.showAllTypes {
521+
fmt.Fprintf(tw, "[ %s", colorize(colorGray, "#[]"+v.Type().Elem().Kind().String()))
522+
fmt.Fprintln(tw)
523+
} else {
524+
fmt.Fprintln(tw, "[")
525+
}
526+
500527
for i := range v.Len() {
501528
if i >= d.maxItems {
502529
indentPrint(tw, indent+1, colorize(colorGray, "... (truncated)\n"))
@@ -515,18 +542,33 @@ func (d *Dumper) printValue(tw *tabwriter.Writer, v reflect.Value, indent int, v
515542
str = string(runes[:d.maxStringLen]) + "…"
516543
}
517544
fmt.Fprint(tw, colorize(colorYellow, `"`)+colorize(colorLime, str)+colorize(colorYellow, `"`))
545+
if d.showAllTypes {
546+
fmt.Fprint(tw, colorize(colorGray, " #"+v.Type().String()))
547+
}
518548
case reflect.Bool:
519549
if v.Bool() {
520550
fmt.Fprint(tw, colorize(colorYellow, "true"))
521551
} else {
522552
fmt.Fprint(tw, colorize(colorGray, "false"))
523553
}
554+
if d.showAllTypes {
555+
fmt.Fprint(tw, colorize(colorGray, " #"+v.Type().String()))
556+
}
524557
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
525558
fmt.Fprint(tw, colorize(colorCyan, fmt.Sprint(v.Int())))
559+
if d.showAllTypes {
560+
fmt.Fprint(tw, colorize(colorGray, " #"+v.Type().String()))
561+
}
526562
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
527563
fmt.Fprint(tw, colorize(colorCyan, fmt.Sprint(v.Uint())))
564+
if d.showAllTypes {
565+
fmt.Fprint(tw, colorize(colorGray, " #"+v.Type().String()))
566+
}
528567
case reflect.Float32, reflect.Float64:
529568
fmt.Fprint(tw, colorize(colorCyan, fmt.Sprintf("%f", v.Float())))
569+
if d.showAllTypes {
570+
fmt.Fprint(tw, colorize(colorGray, " #"+v.Type().String()))
571+
}
530572
case reflect.Func:
531573
fmt.Fprint(tw, colorize(colorGray, v.Type().String()))
532574
default:

godump_test.go

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,6 @@ func TestTheKitchenSink(t *testing.T) {
653653
// Ensure no panic occurred and a sane dump was produced
654654
assert.Contains(t, out, "#") // loosest
655655
assert.Contains(t, out, "Everything") // middle-ground
656-
657656
}
658657

659658
func TestAnsiColorize_Disabled(t *testing.T) {
@@ -1052,5 +1051,55 @@ func TestDumpJSON(t *testing.T) {
10521051

10531052
assert.Equal(t, []any{"foo", float64(123), true}, got)
10541053
})
1054+
}
1055+
1056+
func TestShowAllTypesFlag(t *testing.T) {
1057+
type StrAlias string
1058+
1059+
type ShowTypes struct {
1060+
SignedNumber int
1061+
UnsignedNumber uint
1062+
Float float64
1063+
Str string
1064+
Alias StrAlias
1065+
Boolean bool
1066+
Time time.Time
1067+
Slice []int
1068+
KeyVal map[string]string
1069+
}
1070+
1071+
v := ShowTypes{
1072+
SignedNumber: -10,
1073+
UnsignedNumber: 10,
1074+
Float: 10.10,
1075+
Str: "Hello, World",
1076+
Alias: StrAlias("Hello, World"),
1077+
Boolean: true,
1078+
Time: time.Date(2025, 1, 1, 12, 0, 0, 0, time.UTC),
1079+
Slice: []int{1, 2, 3},
1080+
KeyVal: map[string]string{
1081+
"k1": "v1",
1082+
"k2": "v2",
1083+
},
1084+
}
10551085

1086+
out := stripANSI(NewDumper().DumpStr(v))
1087+
assert.NotContains(t, out, "#int")
1088+
assert.NotContains(t, out, "#uint")
1089+
assert.NotContains(t, out, "#float64")
1090+
assert.NotContains(t, out, "#string")
1091+
assert.NotContains(t, out, "StrAlias")
1092+
assert.NotContains(t, out, "#bool")
1093+
assert.NotContains(t, out, "#[]int")
1094+
assert.NotContains(t, out, "#map[string]string")
1095+
1096+
out = stripANSI(NewDumper(WithShowAllTypes(true)).DumpStr(v))
1097+
assert.Contains(t, out, "#int")
1098+
assert.Contains(t, out, "#uint")
1099+
assert.Contains(t, out, "#float64")
1100+
assert.Contains(t, out, "#string")
1101+
assert.Contains(t, out, "StrAlias")
1102+
assert.Contains(t, out, "#bool")
1103+
assert.Contains(t, out, "#[]int")
1104+
assert.Contains(t, out, "#map[string]string")
10561105
}

0 commit comments

Comments
 (0)