🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 延迟调用(defer) `defer`语句的用途是:含有`defer`语句的函数,会在该函数将要返回之前,调用另一个函数; defer特性: 1. 关键字defer 用于注册延迟调用; 2. defer 不仅限于函数的调用,调用方法也是合法的; 2. 这些调用直到 return 前才被执,因此可以用来做资源清理; 3. 多个defer语句,按先进后出(FILO)的方式执行;哪怕函数或某个延迟调用发生错误,这些调用依旧会被执行; 4. defer语句中的变量,在defer声明时就决定了; 使用场景: 1. 关闭文件句柄 2. 锁资源释放 3. 数据库连接释放 ### 实参取值(Arguments Evaluation) 在 Go 语言中,并非在调用延迟函数的时候才确定实参,而是当执行`defer`语句的时候,就会对延迟函数的实参进行求值 ~~~go func printA(a int) { fmt.Println("value of a in deferred function", a) } func main() { a := 5 defer printA(a) a = 10 fmt.Println("value of a before deferred function call", a) } ~~~ ### defer 碰上闭包 ~~~ func main() { var whatever [5]struct{} for i := range whatever { defer func() { fmt.Println(i) }() } } ~~~ 函数正常执行,由于闭包用到的变量 i 在执行的时候已经变成4,所以输出全都是4 ### defer栈 当一个函数内多次调用`defer`时,Go 会把`defer`调用放入到一个栈中,随后按照后进先出(Last In First Out, LIFO)的顺序执行 ~~~ func TestDeferExample(t *testing.T) { defer fmt.Println("clear") defer fmt.Println("release") defer fmt.Println("close") fmt.Println("main goroutine working") } === RUN TestDeferExample main goroutine working close release clear ~~~