写点什么

【一 Go 到底】第二十一天 ---defer

作者:指剑
  • 2022-10-21
    重庆
  • 本文字数:965 字

    阅读完需:约 1 分钟

【一Go到底】第二十一天---defer

一、defer 简介

1.1 为什么需要 defer

在函数中,程序员经常需要创建资源(比如:数据库连接、文件句柄、锁等),为了在函数执行完毕后,及时的释放资源,Go 的设计者提供 defer (延时机制)。

1.2 快速入门案例

package main
import "fmt"
func sum(num1 int, num2 int) int { // 当执行到defer时,会将defer后面的语句压入到独立的栈中(defer栈),暂时不执行。当函数执行完毕后,再从defer栈中按照 先入后出 的方式执行 defer fmt.Println(" num1 = ", num1) defer fmt.Println(" num2 = ", num2) result := num1 + num2 fmt.Println("result = ", result) return result}
func main() { // result = 30 // num2 = 20 // num1 = 10 sum(10, 20)}
复制代码

二、defer 细节说明

2.1 细节说明

  1. 当 go 执行到一个 defer 时,不会立即执行 defer 后的语句,而是将 defer 后的语句压入到一个栈中(defer 栈),然后继续执行函数下一一个语句。

  2. 当函数执行完毕后,再从 defer 栈中,依次从栈顶取出语句执行(注:遵守栈先入后出的机制)

  3. 在 defer 将语句放入到栈时,也会将相关的值拷贝同时入栈,请看 案例1

2.2 案例演示

2.2.1 案例 1

package main
import "fmt"
func sum(num1 int, num2 int) int { defer fmt.Println(" num1 = ", num1) // 10 defer fmt.Println(" num2 = ", num2) // 20
// 增加两句话 num1++ // 11 num2++ // 21 result := num1 + num2 fmt.Println("result = ", result) return result}
func main() { // result = 32 // num2 = 20 // num1 = 10 // result_main = 32 result_main := sum(10, 20) fmt.Println("result_main = ", result_main)}
复制代码

2.3 最佳实践

defer 最主要的价值是 当函数执行完毕后,可以及时的释放函数创建的资源

2.3.1 案例 2(模拟代码)

对文件进行操作,操作完成后关闭


func openFile(){    file = openfile(文件名)    defer file.close()}
复制代码


对数据库进行模拟操作


func connectDb(){    connect = openDatabase()    defer connect.close()}
复制代码


  1. 在 golang 中通常做法是,创建资源后,例(打开文件,获取数据库链接,获取锁资源)。可以执行 defer file.close() / defer connect.close()

  2. 在 defer 后,可以继续使用创建资源

  3. 当函数完毕后,系统会依次从 defer 栈中,取出语句,关闭资源

  4. 这种机制很简洁,程序员无需考虑关闭资源的时机

发布于: 刚刚阅读数: 4
用户头像

指剑

关注

InfoQ签约作者 2022-07-13 加入

AWS Community Builder,AWS Student Ambassador,阿里云专家博主,OPS社区创始成员

评论

发布
暂无评论
【一Go到底】第二十一天---defer_Go_指剑_InfoQ写作社区