struct String()实现导致堆栈溢出与Sprintf" +"旗

时间:2016-09-27 18:13:11

标签: go

Golang noob问题:为什么我在String()实现方法中使用"%+v"标志作为结构?

我有一个结构,我希望为漂亮的打印实现String()方法。我喜欢here给出的答案,但我不想输入,因此我尝试修改它以使用结构的"%+v"格式标志返回字符串。来自fmt doc:

  

%v打印结构时的默认格式值,加号标志   (%+ v)添加字段名称

如果我只是用fmt.Printf("%+v", color)调用它,这可以正常工作,但是如果我尝试将+标志放在String()实现中,我会得到堆栈溢出(我第一次有机会在stackoverflow.com上询问堆栈溢出"问题;))

我确定我不理解这里的指针引用,或者有一些递归。我怀疑这个菜鸟找到了我的第一个Golang虫子,所以有人可以解释一下吗?

请参阅此处的演示演示https://play.golang.org/p/13_qI8Iwwa

1 个答案:

答案 0 :(得分:6)

请参阅Package fmt Docs

  

除非使用动词%T%p打印,否则为特殊格式   注意事项适用于实现某些接口的操作数。   按申请顺序:

     
      
  1. 如果操作数实现方法String() string,则将调用该方法将对象转换为字符串,然后将该字符串   根据动词的要求格式化(如果有的话)。
  2.         

    避免在

    等情况下递归
    type X string 
    func (x X) String() string { return Sprintf("<%s>", x) }
    
         

    在重复之前转换值:

    func (x X) String() string { return Sprintf("<%s>", string(x)) }
    
         

    无限递归也可以由自引用数据触发   结构,例如包含自身作为元素的切片,if   该类型具有String方法。然而,这种病症很少见   包裹不能防止它们。

内部:

func (c Color) String() string {
    // THIS CAUSES STACK OVERFLOW
    return fmt.Sprint(c)
}

致电

fmt.Sprint(c)
再次以递归方式调用fmt.Println(c)

func (c Color) String() string导致溢出:在The Go Playground上尝试

这也很好:https://play.golang.org/p/NYLtrxUeiA