12

I'm having trouble printing a struct when failing test cases. It's a pointer to a slice of pointers to structs, or *[]*X. The problem is that I need to know the contents of the X-structs inside the slice, but I cannot get it to print the whole chain. It only prints their addresses, since it's a pointer. I need it to follow the pointers.

This is however useless since the function I want to test modifies their contents, and modifying the test code to not use pointers just means I'm not testing the code with pointers (so that wouldn't work).

Also, just looping through the slice won't work, since the real function uses reflect and might handle more than one layer of pointers.

Simplified example:

package main

import "fmt"

func main() {
    type X struct {
        desc string
    }

    type test struct {
        in   *[]*X
        want *[]*X
    }

    test1 := test{
        in: &[]*X{
            &X{desc: "first"},
            &X{desc: "second"},
            &X{desc: "third"},
        },
    }

    fmt.Printf("%#v", test1)
}

example output:

main.test{in:(*[]*main.X)(0x10436180), want:(*[]*main.X)(nil)}

(code is at http://play.golang.org/p/q8Its5l_lL )

Filip Haglund
  • 13,919
  • 13
  • 64
  • 113
  • 7
    Don't use pointers to slices in structures! Slices are already a reference. – Dave C Feb 13 '15 at 20:44
  • %v can't magically guess what kind of output you want. If you want `fmt` output for something formatted in a specific way implement one of `fmt.Stringer` or `fmt.Formatter`. – Dave C Feb 13 '15 at 20:46
  • Also, you may want an `[]X` instead of a `[]*X`. I wrote some about when you'd use each at the bottom of [this answer](http://stackoverflow.com/questions/23542989/pointers-vs-values-in-parameters-and-return-values/23551970#23551970) (which, higher up, discusses what other types (besides slices) are also already references to data). – twotwotwo Feb 13 '15 at 20:57
  • You cannot do that with package fmt. – Volker Feb 13 '15 at 22:42
  • I recommend [go-spew](https://github.com/davecgh/go-spew) for dumping deeply nested values. – Charlie Tumahai Feb 14 '15 at 00:49

2 Answers2

14

I don't think fmt.Printf has the functionality you are looking for.

You can use the https://github.com/davecgh/go-spew library.

spew.Dump(test1)

Pang
  • 9,564
  • 146
  • 81
  • 122
jatin
  • 1,379
  • 8
  • 7
0

You can use the valast (valast.String()) library alternatively. For the example the out is:

test{in: &[]*X{
    {desc: "first"},
    {desc: "second"},
    {desc: "third"},
}}

For spew (spew.Sdump()) it looks like:

(main.test) {
 in: (*[]*main.X)(0xc000098090)((len=3 cap=3) {
  (*main.X)(0xc000088300)({
   desc: (string) (len=5) "first"
  }),
  (*main.X)(0xc000088310)({
   desc: (string) (len=6) "second"
  }),
  (*main.X)(0xc000088320)({
   desc: (string) (len=5) "third"
  })
 }),
 want: (*[]*main.X)(<nil>)
}     
kwarnke
  • 1,424
  • 1
  • 15
  • 10