65 lines
2.0 KiB
Markdown
65 lines
2.0 KiB
Markdown
|
https://mp.weixin.qq.com/s/ZmfwNlq5_A2RgpUSkJQXrQ
|
|||
|
|
|||
|
### defer
|
|||
|
- Go 语言提供的一种延迟调用机制,defer 的运作离不开函数
|
|||
|
- 只有在函数(和方法)内部才能使用 defer
|
|||
|
- defer 关键字后面只能接函数(或方法),这些函数被称为 deferred 函数
|
|||
|
- defer 将它们注册到其所在 Goroutine 中,用于存放 deferred 函数的栈数据结构中,这些 deferred 函数将在执行 defer 的函数退出前,按后进先出(LIFO)的顺序被程序调度执行
|
|||
|
- 无论是执行到函数体尾部返回,还是在某个错误处理分支显式 return,又或是出现 panic,已经存储到 deferred 函数栈中的函数,都会被调度执行
|
|||
|
![](https://blog-heysq-1255479807.cos.ap-beijing.myqcloud.com/blog/wiki/go/defer.jpg)
|
|||
|
![](blog-heysq-1255479807.cos.ap-beijing.myqcloud.com/blog/wiki/go/defer.jpg)
|
|||
|
|
|||
|
blog-heysq-1255479807.cos.ap-beijing.myqcloud.com/blog/2023-12-11-xoomgtcr.png
|
|||
|
|
|||
|
### defer 注意事项
|
|||
|
- 明确哪些函数可以作为 deferred 函数,有返回值的deferred函数的返回值会被自动丢弃
|
|||
|
- 内置函数 append、cap、len、make、new和imag不能被注册为deferred函数,可以包装一层func,进行调用
|
|||
|
- close、copy、delete、print、recover 可以被注册为deferred函数
|
|||
|
```go
|
|||
|
|
|||
|
Functions: 内置函数列表
|
|||
|
append cap close complex copy delete imag len
|
|||
|
make new panic print println real recover
|
|||
|
```
|
|||
|
- 注意 defer 关键字后面表达式的求值时机,defer 关键字后面的表达式,是在将 deferred 函数注册到 deferred 函数栈的时候进行求值的
|
|||
|
```go
|
|||
|
package main
|
|||
|
|
|||
|
import (
|
|||
|
"fmt"
|
|||
|
)
|
|||
|
|
|||
|
func foo1() {
|
|||
|
for i := 0; i <= 3; i++ {
|
|||
|
defer fmt.Println(i)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func foo2() {
|
|||
|
for i := 0; i <= 3; i++ {
|
|||
|
defer func(n int) {
|
|||
|
fmt.Println(n)
|
|||
|
}(i)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func foo3() {
|
|||
|
for i := 0; i <= 3; i++ {
|
|||
|
defer func() {
|
|||
|
fmt.Println(i)
|
|||
|
}()
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func main() {
|
|||
|
fmt.Println("foo1 result:")
|
|||
|
foo1()
|
|||
|
fmt.Println("\nfoo2 result:")
|
|||
|
foo2()
|
|||
|
fmt.Println("\nfoo3 result:")
|
|||
|
foo3()
|
|||
|
}
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
- 知晓 defer 带来的性能损耗
|