You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go中打印变量为何会引发栈溢出?

Go中append操作引发栈溢出的原因

先看触发栈溢出的复现代码:

package main
import "fmt"

func main() {
    values := []any{1,2,3}
    values = append(values[:1],values[1:])
    fmt.Println(values)
}

现象整理

  • 代码执行时会触发栈溢出,且确定是fmt.Println(values)这一行导致的(之前的语句能正常打印提示信息)
  • 若把打印的values换成其他内容(比如0),程序无报错
  • 改用append(values[:1], values[1:]...)(用...展开可变参数),代码正常输出[1 2 3]
  • 单独打印values[0]没问题,但打印values[1]会直接溢出
  • 对比以下正常运行的代码:
package main
import "fmt"

func main() {
    values := append([]any{1},[]any{2,3})
    fmt.Println(values)
}

问题根源

核心问题出在append的参数传递方式和切片底层数组共享导致的循环引用:

  1. append参数类型不匹配:Go的append要求第二个及以后的参数是切片元素类型的值,或者用...展开同类型切片。错误代码里直接传values[1:](一个[]any),没有用...,相当于把整个切片作为单个元素添加到values[:1]里。最终values的结构是[]any{1, []any{2, 3}}。

  2. 循环引用导致无限递归:错误代码里的values[1:]是原切片的子切片,和原切片共享同一个底层数组。当这个子切片被作为元素添加到外层切片后,就形成了循环引用:外层切片的底层数组包含了子切片,而子切片又指向这个底层数组。fmt.Println打印切片时会递归遍历每个元素,遇到子切片就会继续打印它的元素,无限递归下去,最终耗尽栈空间引发溢出。

而改用...展开参数时,append会把values[1:]里的每个元素逐个添加,最终得到正常的[]any{1,2,3},没有循环引用,自然能正常打印。

至于那个正常运行的对比代码,虽然同样是把一个切片作为单个元素添加,但[]any{2,3}是全新创建的切片,和外层切片[]any{1}的底层数组不共享,所以打印时递归到子切片就结束了,不会无限循环。

内容的提问来源于stack exchange,提问作者Flummox

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 17:56:24