網(wǎng)站首頁 編程語言 正文
defer用于資源的釋放,會在函數(shù)返回之前進(jìn)行調(diào)用。如果有多個defer表達(dá)式,調(diào)用順序類似于棧,越后面的defer表達(dá)式越先被調(diào)用。
defer的觸發(fā)時機(jī)
- 包裹著defer語句的函數(shù)返回時
- 包裹著defer語句的函數(shù)執(zhí)行到最后時
- 當(dāng)前goroutine發(fā)生Panic時
當(dāng)前goroutine發(fā)生Panic時
//輸出結(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前 第一個defer在Panic發(fā)生時執(zhí)行,第二個defer在Panic之后聲明,不能執(zhí)行到 func f3() { defer fmt.Println("panic前") panic("panic中") defer fmt.Println("panic后") }
defer,return,返回值的執(zhí)行順序
- 先給返回值賦值
- 執(zhí)行defer語句
- 包裹函數(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,不會改變要返回的那個r值 r *= 7 }(r) return //空的return }
f1的結(jié)果是6。f1是匿名返回值,匿名返回值是在return執(zhí)行時被聲明,因此defer聲明時,還不能訪問到匿名返回值,defer的修改不會影響到返回值。
f2先給返回值r賦值,r=6,執(zhí)行defer語句,defer修改r, r = 42,然后函數(shù)return。
f3是有名返回值,但是因?yàn)閞是作為defer的傳參,在聲明defer的時候,就進(jìn)行參數(shù)拷貝傳遞,所以defer只會對defer函數(shù)的局部參數(shù)有影響,不會影響到調(diào)用函數(shù)的返回值。
閉包與匿名函數(shù)
匿名函數(shù):沒有函數(shù)名的函數(shù)。函數(shù)也是一種類型,一個函數(shù)可以賦值給變量
閉包:可以使用另外一個函數(shù)作用域中的變量的函數(shù)。閉包復(fù)制的是原對象指針,這就很容易解釋延遲引用現(xiàn)象。
for i := 0; i <= 3; i++ { defer func() { fmt.Print(i) } } //輸出結(jié)果時 3,3,3,3 因?yàn)閐efer函數(shù)的i是對for循環(huán)i的引用,defer延遲執(zhí)行,for循環(huán)到最后i是3,到defer執(zhí)行時i就是3 for i := 0; i <= 3; i++ { defer func(i int) { fmt.Print(i) }(i) } //輸出結(jié)果時 3,2,1,0 因?yàn)閐efer函數(shù)的i是在defer聲明的時候,就當(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
原文鏈接:https://blog.csdn.net/hudeyong926/article/details/125743597
相關(guān)推薦
- 2023-02-04 golang?Gorm框架講解_Golang
- 2022-07-22 React警告:Can‘t perform a React state update on an u
- 2022-08-02 C#如何使用Task類解決線程的等待問題_C#教程
- 2022-05-12 寶塔面板配置SSL證書
- 2022-10-19 react封裝Dialog彈框的方法_React
- 2023-01-30 VMware?Tools?啟動腳本未能在虛擬機(jī)中成功運(yùn)行的兩種解決方法_VMware
- 2022-10-06 C#中List<T>存放元素的工作機(jī)制_C#教程
- 2022-03-12 用C語言實(shí)現(xiàn)圣誕樹(簡易版+進(jìn)階版)_C 語言
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支