Golang noob question: Why can I not use the "%+v"
flag for a struct in the String() implementation method?
I have a struct where I want to implement a String()
method for pretty print. I like the answer given here, but I don't like to type, so I'm trying to modify it to return a string using the "%+v"
format flag for structs. from the fmt doc:
%v the value in a default format when printing structs, the plus flag (%+v) adds field names
This works fine if I simply call it with fmt.Printf("%+v", color)
, but if I try to put the +
flag in the String()
implementation, I get a stack overflow (my first chance to ask a "stack overflow" question on stackoverflow.com ;) )
I'm sure I'm not understanding a pointer reference here, or there is some recursion. I doubt this noob found my first Golang bug, so can someone please explain?
see go play demonstration here https://play.golang.org/p/13_qI8Iwwa
See Package fmt Docs:
Except when printed using the verbs
%T
and%p
, special formatting considerations apply for operands that implement certain interfaces. In order of application:
- If an operand implements method
String() string
, that method will be invoked to convert the object to a string, which will then be formatted as required by the verb (if any).To avoid recursion in cases such as
type X string func (x X) String() string { return Sprintf("<%s>", x) }
convert the value before recurring:
func (x X) String() string { return Sprintf("<%s>", string(x)) }
Infinite recursion can also be triggered by self-referential data structures, such as a slice that contains itself as an element, if that type has a String method. Such pathologies are rare, however, and the package does not protect against them.
Inside:
func (c Color) String() string {
// THIS CAUSES STACK OVERFLOW
return fmt.Sprint(c)
}
The call to
fmt.Sprint(c)
or fmt.Println(c)
which calls func (c Color) String() string
again recursively causes overflow: try it on The Go Playground
Also this works fine: https://play.golang.org/p/NYLtrxUeiA