defer语句会将函数推迟到外层函数返回之后执行。
被defer修饰的函数参数会在defer语句执行时就进行求值,但函数本身要等到外层函数返回时才会执行。
这使得defer非常适合用于资源清理、解锁、记录日志等场景,无论外层函数是正常返回还是发生错误,defer修饰的函数都能得到执行。
示例
- 下面输出的顺序是:Start -> End -> n1=11 -> Deferred: This will be printed last -> n1=10
package main
import "fmt"
func main() {
fmt.Println("Start")
defer fmt.Println("Deferred: This will be printed last")
fmt.Println("End")
defer fmt.Println("n1=", n1)
n1 := 10
n1++
fmt.Println("n1=", n1)
}
defer 使用细节
-
当 go 执行到一个 defer 时,不会立即执行 defer 后面的语句,而是将这个语句压入到 defer栈中
-
等到外层函数执行结束时,再按照后进先出的顺序依次执行 defer 栈中的语句。
-
defer 将语句放入栈时,会将相关的值拷贝同时入栈,因此即使 defer 后面的语句在外层函数返回之前被修改了,defer 栈中的语句仍然会使用当时的值。
defer的主要价值
-
确保资源的正确释放:无论函数是正常返回还是发生错误,defer修饰的函数都能得到执行,适合用于关闭文件、网络连接等资源清理。
-
简化代码结构:使用 defer 可以避免在函数中多处编写资源释放的代码,使得代码更简洁、更易读。