// ObjectGoPrintDiff is like ObjectDiff, but uses go-spew to print the objects, // which shows absolutely everything by recursing into every single pointer // (go's %#v formatters OTOH stop at a certain point). This is needed when you // can't figure out why reflect.DeepEqual is returning false and nothing is // showing you differences. This will. func ObjectGoPrintDiff(a, b interface{}) string { s := spew.ConfigState{DisableMethods: true} return StringDiff( s.Sprintf("%#v", a), s.Sprintf("%#v", b), ) }
// DeepHashObject writes specified object to hash using the spew library // which follows pointers and prints actual values of the nested objects // ensuring the hash does not change when a pointer changes. func DeepHashObject(hasher hash.Hash, objectToWrite interface{}) { hasher.Reset() printer := spew.ConfigState{ Indent: " ", SortKeys: true, DisableMethods: true, SpewKeys: true, } printer.Fprintf(hasher, "%#v", objectToWrite) }
// ObjectGoPrintSideBySide prints a and b as textual dumps side by side, // enabling easy visual scanning for mismatches. func ObjectGoPrintSideBySide(a, b interface{}) string { s := spew.ConfigState{ Indent: " ", // Extra deep spew. DisableMethods: true, } sA := s.Sdump(a) sB := s.Sdump(b) linesA := strings.Split(sA, "\n") linesB := strings.Split(sB, "\n") width := 0 for _, s := range linesA { l := len(s) if l > width { width = l } } for _, s := range linesB { l := len(s) if l > width { width = l } } buf := &bytes.Buffer{} w := tabwriter.NewWriter(buf, width, 0, 1, ' ', 0) max := len(linesA) if len(linesB) > max { max = len(linesB) } for i := 0; i < max; i++ { var a, b string if i < len(linesA) { a = linesA[i] } if i < len(linesB) { b = linesB[i] } fmt.Fprintf(w, "%s\t%s\n", a, b) } w.Flush() return buf.String() }