From 9f6de0698720ce154bb00eaf1dc5039adabc2a8b Mon Sep 17 00:00:00 2001 From: motemen Date: Sat, 14 Feb 2015 12:17:29 +0900 Subject: [PATCH] handle circular structures --- printer.go | 37 ++++++++++++++++++++++++++++++------- printer_test.go | 11 +++++++++++ 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/printer.go b/printer.go index 97d50f3..80e1922 100644 --- a/printer.go +++ b/printer.go @@ -23,18 +23,20 @@ func newPrinter(object interface{}) *printer { tw.Init(buffer, indentWidth, 0, 1, ' ', 0) return &printer{ - Buffer: buffer, - tw: tw, - depth: 0, - value: reflect.ValueOf(object), + Buffer: buffer, + tw: tw, + depth: 0, + value: reflect.ValueOf(object), + visited: map[uintptr]bool{}, } } type printer struct { *bytes.Buffer - tw *tabwriter.Writer - depth int - value reflect.Value + tw *tabwriter.Writer + depth int + value reflect.Value + visited map[uintptr]bool } func (p *printer) String() string { @@ -113,6 +115,12 @@ func (p *printer) printMap() { return } + if p.visited[p.value.Pointer()] { + p.printf("%s{...}", p.typeString()) + return + } + p.visited[p.value.Pointer()] = true + p.println("{") p.indented(func() { keys := p.value.MapKeys() @@ -142,6 +150,14 @@ func (p *printer) printSlice() { return } + if p.value.Kind() == reflect.Slice { + if p.visited[p.value.Pointer()] { + p.printf("%s{...}", p.typeString()) + return + } + p.visited[p.value.Pointer()] = true + } + p.println(p.typeString() + "{") p.indented(func() { for i := 0; i < p.value.Len(); i++ { @@ -163,6 +179,12 @@ func (p *printer) printInterface() { } func (p *printer) printPtr() { + if p.visited[p.value.Pointer()] { + p.printf("...") + return + } + p.visited[p.value.Pointer()] = true + if p.value.Elem().IsValid() { p.printf("&%s", p.format(p.value.Elem())) } else { @@ -231,6 +253,7 @@ func (p *printer) nil() string { func (p *printer) format(object interface{}) string { pp := newPrinter(object) pp.depth = p.depth + pp.visited = p.visited if value, ok := object.(reflect.Value); ok { pp.value = value } diff --git a/printer_test.go b/printer_test.go index c5e24ed..4d2b688 100644 --- a/printer_test.go +++ b/printer_test.go @@ -38,6 +38,16 @@ type HogeHoge struct { A interface{} } +type Circular struct { + C *Circular +} + +var c Circular = Circular{} + +func init() { + c.C = &c +} + var ( testCases = []testCase{ {nil, boldCyan("nil")}, @@ -80,6 +90,7 @@ var ( FooPri{Public: "hello", private: "world"}, new(regexp.Regexp), unsafe.Pointer(new(regexp.Regexp)), + &c, } )