1 defer解释
defer
是Go语言中的一个关键字,用于延迟执行函数调用。当一个函数中使用了defer
关键字来延迟执行某个函数调用时,该函数调用会被推迟到函数返回之前执行。
defer
常用于需要在函数返回之前执行一些清理或释放资源的操作,例如关闭文件、释放锁等。defer
还可以用于捕获函数中的错误,并在函数返回之前进行处理。
2 defer注意点
在使用defer
时,需要注意以下几点:
defer
后面必须跟一个函数调用,可以是普通函数、匿名函数或方法。defer
的函数调用参数会在defer
语句执行时被计算,但是函数调用本身不会被执行。- 多个
defer
语句会按照逆序执行,即最后一个defer
语句会最先执行,倒数第二个defer
语句会倒数第二个执行,以此类推。 defer
语句中的函数调用可以修改函数的返回值。当函数中存在多个defer
语句时,最后一个执行的defer
语句可以修改函数的返回值。
3 简单例子
演示了defer
的用法和如何修改返回值:
package main
import "fmt"
func main() {
result := calculate()
fmt.Println(result) // 输出: 6
}
func calculate() int {
num := 3
defer func() {
num *= 2 // 修改返回值
}()
return num
}
在上面的示例中,calculate()
函数中的defer
语句中的匿名函数会在calculate()
函数返回之前执行。在匿名函数中,我们将num
的值乘以2,从而修改了函数的返回值。
需要注意的是,defer
语句中的函数调用对函数的返回值只是进行了一次修改,而不会对后续的返回值产生影响。因此,如果在defer
语句之后还有其他的返回语句,那么这些返回语句的返回值不会受到defer
的影响。
4 执行顺序问题
package main
import "fmt"
func main() {
defer fmt.Println("First defer")
defer fmt.Println("Second defer")
defer fmt.Println("Third defer")
fmt.Println("Hello, World!")
}
在上面的示例中,我们使用了三个defer
语句,分别打印了"First defer"、“Second defer"和"Third defer”。在main()
函数中,我们还打印了"Hello, World!"。
// 输出结果
Hello, World!
Third defer
Second defer
First defer
可以看到,"Hello, World!“是第一个打印出来的,而三个defer
语句则按照逆序执行,最后一个defer
语句"Third defer"最先执行,倒数第二个defer
语句"Second defer"次之,最后是第一个defer
语句"First defer”。
这个示例说明了多个defer
语句的执行顺序是逆序的,最后一个defer
语句会最先执行,倒数第二个defer
语句会倒数第二个执行,以此类推。这种逆序执行的特性可以用于一些需要在函数返回之前进行的清理操作,例如关闭文件、释放资源等。
5 执行顺序复杂例子
func calc(index string, a, b int) int {
ret := a + b
fmt.Println(index, a, b, ret)
return ret
}
func main() {
a := 1
b := 2
defer calc("1", a, calc("10", a, b))
a = 0
defer calc("2", a, calc("20", a, b))
b = 1
}
猜猜正确的执行顺序?
公布正确结果
10 1 2 3
20 0 2 2
2 0 2 2
1 1 3 4