詳解golang?defer?閉包?匿名函數(shù)
defer用于資源的釋放,會(huì)在函數(shù)返回之前進(jìn)行調(diào)用。如果有多個(gè)defer表達(dá)式,調(diào)用順序類似于棧,越后面的defer表達(dá)式越先被調(diào)用。
defer的觸發(fā)時(shí)機(jī)
- 包裹著defer語(yǔ)句的函數(shù)返回時(shí)
- 包裹著defer語(yǔ)句的函數(shù)執(zhí)行到最后時(shí)
- 當(dāng)前goroutine發(fā)生Panic時(shí)
當(dāng)前goroutine發(fā)生Panic時(shí)
//輸出結(jié)果:return前執(zhí)行defer func f1() { defer fmt.Println("return前執(zhí)行defer") return } //輸出結(jié)果:函數(shù)執(zhí)行 // 函數(shù)執(zhí)行到最后 func f2() { defer fmt.Println("函數(shù)執(zhí)行到最后") fmt.Println("函數(shù)執(zhí)行") } //輸出結(jié)果:panic前 第一個(gè)defer在Panic發(fā)生時(shí)執(zhí)行,第二個(gè)defer在Panic之后聲明,不能執(zhí)行到 func f3() { defer fmt.Println("panic前") panic("panic中") defer fmt.Println("panic后") }
defer,return,返回值的執(zhí)行順序
- 先給返回值賦值
- 執(zhí)行defer語(yǔ)句
- 包裹函數(shù)return返回
func f1() int { //匿名返回值 var r int = 6 defer func() { r *= 7 }() return r } func f2() (r int) { //有名返回值 defer func() { r *= 7 }() return 6 } func f3() (r int) { //有名返回值 defer func(r int) { r *= 7 }(r) return 6 }
f1的執(zhí)行結(jié)果是6, f2的執(zhí)行結(jié)果是42,f3的執(zhí)行結(jié)果是6
最后看example3。它改寫后變成
func f1() (r int) { r = 6 //給返回值賦值 func(r int) { //這里改的r是傳值傳進(jìn)去的r,不會(huì)改變要返回的那個(gè)r值 r *= 7 }(r) return //空的return }
f1的結(jié)果是6。f1是匿名返回值,匿名返回值是在return執(zhí)行時(shí)被聲明,因此defer聲明時(shí),還不能訪問到匿名返回值,defer的修改不會(huì)影響到返回值。
f2先給返回值r賦值,r=6,執(zhí)行defer語(yǔ)句,defer修改r, r = 42,然后函數(shù)return。
f3是有名返回值,但是因?yàn)閞是作為defer的傳參,在聲明defer的時(shí)候,就進(jìn)行參數(shù)拷貝傳遞,所以defer只會(huì)對(duì)defer函數(shù)的局部參數(shù)有影響,不會(huì)影響到調(diào)用函數(shù)的返回值。
閉包與匿名函數(shù)
匿名函數(shù):沒有函數(shù)名的函數(shù)。函數(shù)也是一種類型,一個(gè)函數(shù)可以賦值給變量
閉包:可以使用另外一個(gè)函數(shù)作用域中的變量的函數(shù)。閉包復(fù)制的是原對(duì)象指針,這就很容易解釋延遲引用現(xiàn)象。
for i := 0; i <= 3; i++ { defer func() { fmt.Print(i) } } //輸出結(jié)果時(shí) 3,3,3,3 因?yàn)閐efer函數(shù)的i是對(duì)for循環(huán)i的引用,defer延遲執(zhí)行,for循環(huán)到最后i是3,到defer執(zhí)行時(shí)i就是3 for i := 0; i <= 3; i++ { defer func(i int) { fmt.Print(i) }(i) } //輸出結(jié)果時(shí) 3,2,1,0 因?yàn)閐efer函數(shù)的i是在defer聲明的時(shí)候,就當(dāng)作defer參數(shù)傳遞到defer函數(shù)中
匿名函數(shù)
func main() { /* 匿名函數(shù)切片初始化 */ fns := [](func(x int) int){ func(x int) int { return x + 1 }, func(x int) int { return x + 113 }, } println(fns[1](100)) /* 結(jié)構(gòu)體初始化 */ d := struct { fn func() string }{ fn: func() string { return "Hello, World!" }, } println(d.fn()) fc := make(chan func() string, 2) fc <- func() string { return "Hello, World!" } println((<-fc)()) }
閉包
package main import "fmt" func test() func() { x := 100 fmt.Printf("x (%p) = %d\n", &x, x) return func() { fmt.Printf("x (%p) = %d\n", &x, x) } } func main() { f := test() f() }
輸出:
x (0xc42007c008) = 100
x (0xc42007c008) = 100
到此這篇關(guān)于golangdefer閉包匿名函數(shù)的文章就介紹到這了,更多相關(guān)golangdefer匿名函數(shù)內(nèi)容請(qǐng)搜索本站以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持本站!
版權(quán)聲明:本站文章來源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請(qǐng)保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場(chǎng),如有內(nèi)容涉嫌侵權(quán),請(qǐng)聯(lián)系alex-e#qq.com處理。