运行时:goroutine 堆栈超过 1000000000 字节限制,致命错误:打印嵌套结构时堆栈溢出

Posted

技术标签:

【中文标题】运行时:goroutine 堆栈超过 1000000000 字节限制,致命错误:打印嵌套结构时堆栈溢出【英文标题】:runtime: goroutine stack exceeds 1000000000-byte limit, fatal error: stack overflow on printing a nested struct 【发布时间】:2017-07-24 20:45:00 【问题描述】:

我有一个嵌套结构。

type ConfigOne struct 
    // Daemon section from config file.
    Daemon daemon

type daemon struct 
    Loglevel int
    Logfile string

我在该类型上有一个 String() string 方法,我试图将嵌套的结构元素返回为

func (c ConfigOne)String()  string
    return fmt.Sprintf("%+v\n", c)

当我尝试将其打印为

c := &modules.ConfigOne
c.Daemon.Loglevel = 1
c.Daemon.Logfile = "/tmp/test.log"
modules.Logger.Infoln(c.String())

我收到了错误

运行时:goroutine 堆栈超过 1000000000 字节的限制 致命错误:堆栈溢出

运行时堆栈: runtime.throw(0x6ea3b7, 0xe) ...

通过错误后,我可以看到类似于下面的重复行

modules/structs.go:31 +0x77 fp=0xc440100398 sp=0xc440100328 go-consume/modules.(*ConfigOne).String(0xc42abcb4e0, 0x70bc08, 0xc42abd6300) :1 +0x64 fp=0xc4401003d8 sp=0xc440100398 fmt.(*pp).handleMethods(0xc42abd6300, 0xc400000076, 0x410301)

最后,在死之前,

modules/structs.go:31 +0xc0 fp=0xc440103d18 sp=0xc440103ca8 ...省略了其他帧...

goroutine 17 [系统调用,锁定到线程]: runtime.goexit()

我相信这是由于进入一些无限递归造成的。

我碰巧找到了原因并到达了here,我认为这是同一个问题。但是我无法理解该线程中的解释。

如果我尝试将单个嵌套结构打印为

func (c ConfigOne)String() string
    //return fmt.Sprintf("%+v\n", c.Daemon.Loglevel)
    return fmt.Sprintf("%+v\n", c.Daemon)

工作正常,日志显示字段为

2017/03/05 01:28:25 go-consume.go:38: INFO: Loglevel:1 Logfile:/tmp/test.log

谁能解释一下以前的 String() 方法是如何导致无限递归和堆栈溢出的,克服这个问题的最佳方法是什么?

【问题讨论】:

【参考方案1】:

%v%+v 格式使用 String() 的值(如果类型实现了它)。因此,在该类型的 String() 函数内的类型上使用 %+v 会导致无限递归。您必须构造自己的字符串,而不是在 String() 函数中使用 %+v,以任何您认为合适的方式显示结构的内容。

【讨论】:

谢谢@andy-schweig。

以上是关于运行时:goroutine 堆栈超过 1000000000 字节限制,致命错误:打印嵌套结构时堆栈溢出的主要内容,如果未能解决你的问题,请参考以下文章

如何转储 goroutine 堆栈跟踪?

Delphi 异常处理

Golang教程:goroutine协程

向 exec.Cmd.StdinPipe() 写入超过 4K 字节

C ++模板堆栈映射/多映射[关闭]

Golang之goroutine