go-spew icon indicating copy to clipboard operation
go-spew copied to clipboard

Feature request: Go syntax deep printing

Open soroushjp opened this issue 10 years ago • 7 comments

Often, I am writing units tests and have expected outputs from a function that are structs with many fields, or arrays of structs so there may be >100 fields. I'd like to get one deep print of the struct I am comparing against, get a Go syntax representation, and then edit field values as necessary to write good unit tests.

I currently use a combination ginkgo/gomega Expect output, which is close but not Go syntax, or fmt's %#v printing which is Go syntax but does not dereference pointers. This would be extremely useful. If this not on the roadmap at all, I would be happy to try and implement it in go-spew.

soroushjp avatar Jun 08 '15 18:06 soroushjp

Hey @soroushjp,

See #6. I had the exact same desire 2 years ago, and that's what my go-goon fork tries to achieve.

If you try it out, let me know how it goes, and I'm interested in making it better. I use it myself very frequently.

dmitshur avatar Jun 08 '15 18:06 dmitshur

Thanks @shurcooL, will check it out and let you know if it helps, appreciate the message!

soroushjp avatar Jun 09 '15 16:06 soroushjp

:+1: on this feature request. I'd find it immensely useful, editing the spew output by hand is not fun.

nathanleclaire avatar Oct 30 '15 20:10 nathanleclaire

I considered this during initial development, but the main issue is that there are several cases where there is no clear Go syntax to recreate a given data structure. For example, consider the following:

type Inner struct {
    Field1 string
    Field2 **int
}

In this case, there is no clear Go syntax such that you can initialize an instance of Inner due to the double pointer to an int.

The same issue arises in many scenarios such as double pointers to any type, single pointers to native types, interfaces, etc.

I would certainly accept an implementation, but I suspect you'll run into some situations that are unclear how the syntax should be generated. For example, with the provided code above, it would require the use of local variables (then naming them something reasonable is another challenge).

davecgh avatar Nov 05 '15 19:11 davecgh

Yeah, I saw your comment in the other thread after posting. I agree it's a difficult issue, maybe another small tool could be created for doing that in the cases where it can actually be done sanely.

nathanleclaire avatar Nov 05 '15 20:11 nathanleclaire

FWIW, this is how go-goon currently deals with that situation:

type Inner struct {
    Field1 string
    Field2 **int
}
i := 123
ip := &i
v := Inner{
    Field1: "Text.",
    Field2: &ip,
}
goon.Dump(v)

// Output:
// (Inner)(Inner{
//  Field1: (string)("Text."),
//  Field2: (**int)(&&123),
// })

It's not valid Go code. However, IMO it's consistent and pretty readable, and only 1 line needs to be modified to make it valid Go. These situations come up less frequently, so it's still useful that the rest is dumped in Go syntax notation. It would've also been valid Go code if Field2 value were nil.

dmitshur avatar Nov 06 '15 01:11 dmitshur

For the benefit of anyone interested, there's now a package for printing data as Go code: https://github.com/Mitranim/repr

It's made mostly for code generation, producing pretty code that you would write yourself (unlike the goon fork). 😄

There are some limitations; let me know if any critical functionality is missing.

mitranim avatar Oct 23 '18 08:10 mitranim