defer
- 在函數(shù)返回之前, 調(diào)用defer函數(shù)的操作;
- 函數(shù)內(nèi)可以有多個(gè)defered函數(shù), 但是這些defered函數(shù)在函數(shù)返回時(shí)遵守后進(jìn)先出的原則
- 函數(shù)命名的返回值跟defered函數(shù)一起使用,,函數(shù)的返回值有可能被defer更改。
package main
import "fmt"
func main() {
fmt.Println(f()) //輸出 3
fmt.Println(g())//輸出 5
fmt.Println(h())//輸出 1
}
func f() (rint) {
r= 2
defer func() {
r++
}()
return r
}
func g() (r int) {
t := 5
defer func() {
t = t + 5
}()
return t
}
func h() (r int) {
defer func(r int) {
r = r + 5
}(r)
return 1
}
- return其實(shí)應(yīng)該包含前后兩個(gè)步驟:
1.給返回值賦值(若為有名返回值則直接賦值监婶,若為匿名返回值則先聲明再賦值)莫矗;
2.調(diào)用RET返回指令并傳入返回值,而RET則會(huì)檢查defer是否存在,若存在就先逆序插播defer語(yǔ)句,最后RET攜帶返回值退出函數(shù);
上述例子中:
f()
是有名返回值昆淡,執(zhí)行return先給result賦值,此時(shí)r=2刽严,再執(zhí)行defer昂灵,執(zhí)行后r=3,最后返回r= 3舞萄;
g()
有名返回值眨补,執(zhí)行return先給r賦值,r = t =5倒脓,再執(zhí)行defer撑螺,此時(shí)修改了t = 10,最后返回的是r=5.
h()
有名返回值崎弃,執(zhí)行return先給r賦值r=1, 但defer里面的r是形參甘晤,不會(huì)改變到外層的返回值r的值.
panic
類似其它語(yǔ)言的Exception,即異常饲做。
recover
類似其它語(yǔ)言的try catch.
- recover如果想起作用的話, 必須在defered函數(shù)中使用.
- 在正常函數(shù)執(zhí)行過(guò)程中, 調(diào)用recover沒(méi)有任何作用, 他會(huì)返回nil. 如這樣:fmt.Println(recover()) // nil
- 如果當(dāng)前的goroutine panic了, 那么recover將會(huì)捕獲這個(gè)panic的值, 并且讓程序正常執(zhí)行下去, 不會(huì)讓程序crash.
例子:
package main
import "fmt"
func main() {
defer func() {
if err := recover(); err!= nil {
fmt.Println("Error message:", err)
}
}()
defer func() {
fmt.Println("Don't Fuck")
}()
panic("Fuck you")
}