struct String() implemention causes stack overflow

2019-08-02 19:06发布

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

标签: go
1条回答
爷、活的狠高调
2楼-- · 2019-08-02 19:41

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:

  1. 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

查看更多
登录 后发表回答