跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
Go 延迟执行defer
”︁(章节)
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= Go延迟执行defer = '''defer'''是Go语言中用于延迟执行函数调用的关键字,它会在当前函数返回前执行被延迟的函数。这种机制常用于资源清理(如关闭文件、释放锁等),确保资源在任何执行路径下都能被正确释放。 == 基本介绍 == defer语句会将函数调用推入一个栈中,当外层函数返回时,栈中的函数会按照后进先出(LIFO)的顺序执行。这意味着最后被defer的函数会最先执行。 === 语法 === <syntaxhighlight lang="go"> defer functionCall(arguments) </syntaxhighlight> == 基本示例 == 以下是一个简单的defer使用示例: <syntaxhighlight lang="go"> package main import "fmt" func main() { defer fmt.Println("这是第一个defer语句") fmt.Println("主函数执行") defer fmt.Println("这是第二个defer语句") } </syntaxhighlight> '''输出:''' <pre> 主函数执行 这是第二个defer语句 这是第一个defer语句 </pre> '''解释:''' 1. 主函数开始执行 2. 第一个defer语句被注册 3. 打印"主函数执行" 4. 第二个defer语句被注册 5. 主函数结束,开始执行defer栈中的函数 6. 按照LIFO顺序,先执行第二个defer,再执行第一个defer == 关键特性 == === 参数即时求值 === defer函数的参数会在defer语句执行时立即求值,而非在真正调用时求值。 <syntaxhighlight lang="go"> package main import "fmt" func main() { i := 0 defer fmt.Println("defer中的i:", i) i++ fmt.Println("主函数中的i:", i) } </syntaxhighlight> '''输出:''' <pre> 主函数中的i: 1 defer中的i: 0 </pre> === 多个defer的执行顺序 === defer语句会按照后进先出的顺序执行: <mermaid> graph LR A[defer 1] --> B[defer 2] B --> C[defer 3] C --> D[执行顺序: 3 → 2 → 1] </mermaid> == 实际应用场景 == === 1. 资源清理 === 最常见的用途是确保资源被正确释放。 <syntaxhighlight lang="go"> package main import ( "fmt" "os" ) func main() { file, err := os.Open("example.txt") if err != nil { fmt.Println("打开文件出错:", err) return } defer file.Close() // 确保文件被关闭 // 处理文件内容... fmt.Println("文件处理中...") } </syntaxhighlight> === 2. 锁的释放 === 确保锁在任何情况下都会被释放。 <syntaxhighlight lang="go"> package main import "sync" var mu sync.Mutex func criticalSection() { mu.Lock() defer mu.Unlock() // 确保锁被释放 // 临界区代码... } </syntaxhighlight> === 3. 记录函数执行时间 === 利用defer记录函数执行时间。 <syntaxhighlight lang="go"> package main import ( "fmt" "time" ) func measureTime() { defer func(start time.Time) { fmt.Printf("函数执行耗时: %v\n", time.Since(start)) }(time.Now()) // 模拟耗时操作 time.Sleep(1 * time.Second) } func main() { measureTime() } </syntaxhighlight> == 注意事项 == 1. '''不要在循环中使用defer''',除非你明确知道自己在做什么,因为这可能导致资源延迟释放。 2. defer有一定的性能开销,在性能敏感的代码中应谨慎使用。 3. defer函数中的返回值会被丢弃,除非使用命名返回值。 === 命名返回值与defer === defer可以修改命名返回值: <syntaxhighlight lang="go"> package main import "fmt" func example() (result int) { defer func() { result = 42 // 修改命名返回值 }() return 0 // 这个返回值会被defer覆盖 } func main() { fmt.Println(example()) // 输出: 42 } </syntaxhighlight> == 数学表达 == defer的执行可以表示为函数调用栈的操作。设函数<math>f</math>中有<math>n</math>个defer调用<math>d_1, d_2, ..., d_n</math>,则执行顺序为: <math> \text{ExecutionOrder} = (d_n, d_{n-1}, ..., d_1) </math> == 总结 == defer是Go语言中一个强大的特性,它通过简单的语法提供了可靠的资源管理机制。理解defer的执行时机和参数求值规则对于编写健壮的Go代码至关重要。在实际开发中,defer常用于: * 资源清理(文件、网络连接等) * 锁的释放 * 执行时间测量 * 错误恢复(与recover配合使用) 通过合理使用defer,可以大大减少资源泄漏的风险,使代码更加简洁可靠。 [[Category:编程语言]] [[Category:Go]] [[Category:Go 控制流]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)