defer #
Go 处理 defer 和 return 的顺序为:
- 计算 return 语句的返回值
- 赋值给匿名 / 有名返回值
- 执行 defer
- return 退出函数
Defer 的用途跟其他语言的 ensure
或 finally
类似。
当 defer 释放锁遇到尾递归,会产生死锁 #
如果一个函数中所有递归形式的调用都出现在函数的末尾,我们称这个递归函数是尾递归的。
计算 return 语句的值,赋值给匿名/有名返回值 -> defer -> return 退出函数
var mut = sync.Mutex{}
func tailRec(i int) int {
mut.Lock() // 加锁
defer mut.Unlock() // defer 释放锁
if i == 10 {
return i
}
i++
return tailRec(i) // return 尾递归
}
以上代码执行会发生死锁,原因是 return 语句后的命令先执行,赋值给匿名返回值后,再调用 defer, 因此尾递归中 tailRec 的加锁会在 defer 释放锁之前进行,形成死锁。
参考:
返回值求值 #
// 匿名返回值
func test_unnamed()(int) {
var i int
defer func() {
i++
fmt.Println("defer a:", i)
}()
defer func() {
i++
fmt.Println("defer b :", i)
}()
return i // 0
}
// 具名返回值
func test_named()(i int) {
defer func() {
i++
fmt.Println("defer c:", i)
}()
defer func() {
i++
fmt.Println("defer d :", i)
}()
return i // 2
}
叶王 © 2013-2024 版权所有。如果本文档对你有所帮助,可以请作者喝饮料。