Go defer函数 延迟执行

2022-10-29 11:48:40

defer


func TestDefer(t *testing.T) {

defer func() { //后面可以是命名函数,或者匿名函数,总之是函数调用
t.Log("Clear resources")
}()
t.Log("Started")
panic("Fatal error”) //defer仍会执⾏,如果是其他语句放在Panic之后,那么这行语句是不可达的,也就是Panic后面的语句是不可执行的

}


defer的函数调用不会立刻执行,而是会执行Panic语句,执行完了在函数返回前才会执行defer的函数,
依据这种特性,可能会想到在java里面的try finally的结构,这个类似于finally,最后返回时候执行的。

这有什么用呢,通常都是清理某些资源,释放某些锁,不管是报了异常还是异常退出了,都不会忘记将我们的锁/资源释放掉,以免导致资源的浪费,导致程序被锁住。

这里抛出了Panic,这里是程序异常中断,在go里面代表不可修复的错误。即便是在Panic的情况下,defer后面的函数也是会执行的。
defer 关键字用户声明函数,不论函数是否发生错误都在函数执行最后执行(return 之前)若使用 defer 声明多个函数,则按照声明的顺序,先声明后执行(堆) 常用来做资源释放,记录日志等工作。

defer后面一般是加匿名函数的调用

fmt.Println("start")
defer func() {
   fmt.Println("defer")
}()
fmt.Println("end")


start
end
defer

defer的作用就是延时执行,defer延时到什么时候呢,延时到函数退出之前执行。

mt.Println("start")
defer func() {
   fmt.Println("defer1")
}()

defer func() {
   fmt.Println("defer2")
}()


fmt.Println("end")


start
end
defer2
defer1

可以看到是堆栈的模式,谁先声明,最后执行。

Deferred 函数


在一个自定义函数中,你打开了一个文件,然后需要关闭它以释放资源。不管你的代码执行了多少分支,是否出现了错误,文件是一定要关闭的,这样才能保证资源的释放。

如果这个事情由开发人员来做,随着业务逻辑的复杂会变得非常麻烦,而且还有可能会忘记关闭。基于这种情况,Go 语言为我们提供了 defer 函数,可以保证文件关闭后一定会被执行,不管你自定义的函数出现异常还是错误。

延时执行有个关键字defer,defer后面跟着的是函数调用函数调用就是要加括号的

下面的代码是 Go 语言标准包 ioutil 中的 ReadFile 函数,它需要打开一个文件,然后通过 defer 关键字确保在 ReadFile 函数执行结束后,f.Close() 方法被执行,这样文件的资源才一定会释放。

func ReadFile(filename string) ([]byte, error) {

   f, err := os.Open(filename)

   if err != nil {

      return nil, err

   }

   defer f.Close()

   //省略无关代码

   return readAll(f, n)

}

defer 关键字用于修饰一个函数或者方法,使得该函数或者方法在返回前才会执行,也就说被延迟,但又可以保证一定会执行。

以上面的 ReadFile 函数为例,被 defer 修饰的 f.Close 方法延迟执行,也就是说会先执行 readAll(f, n),然后在整个 ReadFile 函数 return 之前执行 f.Close 方法。

defer 语句常被用于成对的操作,如文件的打开和关闭,加锁和释放锁,连接的建立和断开等。不管多么复杂的操作,都可以保证资源被正确地释放。

  • 作者:富士康质检员张全蛋
  • 原文链接:https://blog.csdn.net/qq_34556414/article/details/122981971
    更新时间:2022-10-29 11:48:40