首页 > 后端开发 > C++ > 正文

如何正确使用Golang的defer关键字 讲解延迟执行的常见陷阱

P粉602998670
发布: 2025-07-08 09:40:02
原创
489人浏览过

golang中,defer关键字用于在函数返回前执行指定操作,但使用时需注意三个常见陷阱。首先,defer语句的参数在声明时即求值,而非执行时,因此若希望获取变量最终值,应使用闭包延迟求值。其次,在循环中频繁使用defer可能导致性能下降和内存压力,建议避免在循环体中直接使用defer或采用匿名函数限制defer作用域。最后,defer在return之后执行,若使用匿名返回值,defer修改不会影响返回结果,此时应改用命名返回值以达到预期效果。

如何正确使用Golang的defer关键字 讲解延迟执行的常见陷阱

在Golang中,defer关键字是一个非常实用的特性,它允许你在函数返回之前执行某些操作,比如关闭文件、释放资源等。但如果你不注意使用方式,很容易掉进一些常见的“坑”里。

如何正确使用Golang的defer关键字 讲解延迟执行的常见陷阱

defer的基本用法和执行时机

defer的作用很简单:将一个函数调用推迟到当前函数返回之前执行。不管函数是正常返回还是发生了panic,被defer的语句都会被执行。

如何正确使用Golang的defer关键字 讲解延迟执行的常见陷阱

例如:

立即学习go语言免费学习笔记(深入)”;

func main() {
    defer fmt.Println("world")
    fmt.Println("hello")
}
登录后复制

输出会是:

如何正确使用Golang的defer关键字 讲解延迟执行的常见陷阱
hello
world
登录后复制

这里的关键点在于:defer是在函数返回前执行,而不是在当前代码块结束时执行。这意味着你可以在函数中多次使用defer,它们会按照后进先出(LIFO)的顺序执行。

常见陷阱一:参数求值时机

这是最容易让人误解的地方。defer后面的函数参数会在defer语句执行时就被求值,而不是等到函数返回时才求值。

举个例子:

func badExample() {
    i := 1
    defer fmt.Println(i)
    i++
}
登录后复制

很多人以为输出是2,但实际输出是1。因为i的值在defer语句执行的时候就已经确定了。

建议:如果你想延迟执行某个表达式的结果,可以考虑用闭包:defer func() { fmt.Println(i) }()

这样就能在函数返回时获取最新的i值。

常见陷阱二:在循环中使用defer可能导致性能问题

有些人喜欢在循环里用defer来处理资源释放,比如打开多个文件然后一个个defer关闭。虽然语法上没问题,但这样做会导致:

先见AI
先见AI

数据为基,先见未见

先见AI95
查看详情 先见AI
  • 每次循环都注册一个defer函数,影响性能
  • defer函数堆积,可能造成内存压力

比如:

for _, file := range files {
    f, _ := os.Open(file)
    defer f.Close()
}
登录后复制

这段代码看似没问题,但如果循环次数很多,defer累积的数量也会很大。

建议:

  • 在循环内部避免直接使用defer
  • 可以手动管理资源,在循环结束后统一释放
  • 或者在每次循环中使用匿名函数包裹defer:
for _, file := range files {
    func() {
        f, _ := os.Open(file)
        defer f.Close()
        // do something with f
    }()
}
登录后复制

这样每个defer只作用于当前的匿名函数,不会堆积太多defer调用。

常见陷阱三:defer与return的顺序搞不清

还有一个容易混淆的地方是:defer是在return之后、函数真正退出之前执行的。

看这个例子:

func returnAndDefer() int {
    var i int
    defer func() {
        i++
    }()
    return i
}
登录后复制

这个函数返回的是0,不是1。因为return i已经把返回值确定下来了,defer修改的是变量本身,并不会影响返回结果。

建议:

  • 如果你希望defer能影响返回值,可以用命名返回值:
func namedReturn() (result int) {
    defer func() {
        result++
    }()
    return 0
}
登录后复制

这时返回的就是1了。


基本上就这些。defer是个好工具,但要小心它的行为细节,特别是在参数求值、循环结构和返回值上的表现。用得好了,能让你的代码更简洁清晰;用得不当,反而埋下不少隐患。

以上就是如何正确使用Golang的defer关键字 讲解延迟执行的常见陷阱的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号