MST

星途 面试题库

面试题:Go语言defer在循环中的执行顺序

在Go语言中,对于如下代码,输出结果是什么,为什么?如果想要按1到5顺序输出defer的内容,该如何修改代码? ```go package main import "fmt" func main() { for i := 1; i <= 5; i++ { defer fmt.Println(i) } } ```
28.8万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 原代码输出结果及原因
    • 输出结果:5 4 3 2 1
    • 原因:在Go语言中,defer语句会将其后面跟随的函数延迟到包含该defer语句的函数结束时执行。这些被延迟执行的函数会以栈的方式进行存储,后进先出(LIFO)。在for循环中,每次迭代都会将fmt.Println(i)函数压入defer栈,当for循环结束时,main函数也即将结束,此时会从defer栈中依次弹出函数并执行,由于是栈结构,最后压入的fmt.Println(5)最先执行,以此类推,所以输出顺序是5 4 3 2 1。
  2. 修改代码以按1到5顺序输出
package main

import "fmt"

func main() {
    var stack []int
    for i := 1; i <= 5; i++ {
        stack = append(stack, i)
    }
    for len(stack) > 0 {
        index := len(stack) - 1
        defer fmt.Println(stack[index])
        stack = stack[:index]
    }
}

这里先将数字1到5存入切片stack,然后通过defer结合从切片栈顶弹出元素的方式,保证defer执行时按1到5的顺序输出。另一种方式是使用匿名函数结合闭包:

package main

import "fmt"

func main() {
    for i := 1; i <= 5; i++ {
        j := i
        defer func() {
            fmt.Println(j)
        }()
    }
}

这里通过创建局部变量j,将每次循环的i值捕获到闭包中,避免了defer执行时i已经是循环结束后的最终值的问题,从而按1到5顺序输出。