Golang Go语言中延迟调用的问题

发布于 1周前 作者 vueper 来自 Go语言

Golang Go语言中延迟调用的问题

package main

import “fmt”

func main() { for i := 0; i < 3; i++ { defer func() { fmt.Println(“a:”, i) }() } }

输出是:
a:3
a:3
a:3


package main

import “fmt”

func main() { for i := 0; i < 3; i++ { i := i defer func() { fmt.Println(“a:”, i) }() } }

输出是:
a:2
a:1
a:0

为什么两个的运行结果会不一样呢?


更多关于Golang Go语言中延迟调用的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

12 回复

闭包问题

更多关于Golang Go语言中延迟调用的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在循环结束时 defer 才会执行,
第一个输出的是 for 语句的 i 的值,这时候 i 已经是 3 了( (3<3)!=true,循环结束 )。

第二个输出的是局部变量 i,当然是 2、1、0.

不过我有个疑问,如何理解第二个回答中的例子

两个关键点:
1. 所有循环步共享同一个循环变量 i
2. 延迟调用在循环之后(程序退出之前)执行

第二个例子中的左 i 和右 i (循环变量)不同,每个循环步有自己独立的左 i

第一个只有一个变量;第二个有四个变量

闭包是引用传值

第二个循环中每次都会定义 i,闭包中引用的是每次新定义的 i 的值,依次是 0 1 2,defer 先入后出打印出来就是 2 1 0

闭包传值问题。go 是按值传递,参见 https://github.com/golang/go/wiki/CommonMistakes

go 只有按值传递,没有引用传值,有值类型和引用类型,楼主的问题是 loop goroutime 的执行问题

在Golang(Go语言)中,延迟调用通常通过内置的 defer 关键字来实现。defer 语句会将一个函数调用延迟到包含它的函数即将返回时执行,这常用于资源清理、解锁互斥锁、关闭文件或网络连接等操作。

使用场景

  1. 资源释放:在文件操作或数据库连接中,使用 defer 确保资源在函数退出时被正确释放。
  2. 互斥锁解锁:在多线程编程中,通过 defer 确保互斥锁在函数结束时被解锁,避免死锁。
  3. 日志记录:在函数入口和出口处记录日志,通过 defer 实现函数结束时自动记录退出日志。

注意事项

  • 执行顺序defer 语句按照后进先出的顺序执行,即最后 defer 的函数最先执行。
  • 参数求值defer 语句中的函数参数在 defer 时立即求值,而不是在函数实际执行时求值。
  • 异常处理:即使在发生panic时,defer 语句也会被执行,这对于恢复程序的正常运行或记录错误信息非常有用。

示例

func readFile(filename string) {
    file, err := os.Open(filename)
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close() // 确保文件在函数结束时被关闭
    // 处理文件内容
}

总之,defer 是Go语言中一个非常有用的特性,它简化了资源管理,并提高了代码的健壮性和可读性。

回到顶部