struct String()实现导致Sprintf"+"堆栈溢出.旗帜 [英] struct String() implemention causes stack overflow with Sprintf "+" flag

查看:71
本文介绍了struct String()实现导致Sprintf"+"堆栈溢出.旗帜的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Golang noob question: Why can I not use the "%+v" flag for a struct in the String() implementation method?

我有一个要在其中实现 String()方法以进行漂亮打印的结构.我喜欢在此处给出的答案,但是我不喜欢键入,因此我尝试对其进行修改以返回字符串对结构使用%+ v" 格式标志.来自 fmt 文档:

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在打印结构时使用默认格式的值,加号(%+ v)添加字段名称

%v the value in a default format when printing structs, the plus flag (%+v) adds field names

如果我简单地使用 fmt.Printf(%+ v",color)调用它,那么效果很好,但是如果我尝试将 + 标志放在 String()实现,我发生了堆栈溢出(我第一次有机会在stackoverflow.com上问堆栈溢出"问题;))

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 ;) )

我确定我在这里不理解指针引用,否则会有一些递归.我怀疑这个菜鸟发现了我的第一个Golang错误,所以有人可以解释一下吗?

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?

在此处查看围棋演示 https://play.golang.org/p/13_qI8Iwwa

推荐答案

请参见打包fmt文档:

除了使用动词%T %p 进行打印时,特殊格式注意事项适用于实现某些接口的操作数.按申请顺序:

Except when printed using the verbs %T and %p, special formatting considerations apply for operands that implement certain interfaces. In order of application:

  1. 如果操作数实现方法 String()string ,则将调用该方法将对象转换为字符串,然后将其转换为字符串根据动词的要求进行格式设置(如果有的话).
  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).

在诸如此类的情况下避免递归

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)) }

无限递归也可以由自引用数据触发结构,例如包含自身作为元素的切片该类型具有String方法.但是,这种病理很少见,并且该包装无法防止它们受到侵害.

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.


内部:

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

致电

fmt.Sprint(c)

再次递归调用 func(c Color)String()字符串

fmt.Println(c)会导致溢出:请在

or fmt.Println(c) which calls func (c Color) String() string again recursively causes overflow: try it on The Go Playground

这也可以正常工作: https://play.golang.org/p/NYLtrxUeiA

这篇关于struct String()实现导致Sprintf"+"堆栈溢出.旗帜的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆