網站首頁 編程語言 正文
defer用于資源的釋放,會在函數返回之前進行調用。如果有多個defer表達式,調用順序類似于棧,越后面的defer表達式越先被調用。
defer的觸發時機
- 包裹著defer語句的函數返回時
- 包裹著defer語句的函數執行到最后時
- 當前goroutine發生Panic時
當前goroutine發生Panic時
//輸出結果:return前執行defer func f1() { defer fmt.Println("return前執行defer") return } //輸出結果:函數執行 // 函數執行到最后 func f2() { defer fmt.Println("函數執行到最后") fmt.Println("函數執行") } //輸出結果:panic前 第一個defer在Panic發生時執行,第二個defer在Panic之后聲明,不能執行到 func f3() { defer fmt.Println("panic前") panic("panic中") defer fmt.Println("panic后") }
defer,return,返回值的執行順序
- 先給返回值賦值
- 執行defer語句
- 包裹函數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的執行結果是6, f2的執行結果是42,f3的執行結果是6
最后看example3。它改寫后變成
func f1() (r int) { r = 6 //給返回值賦值 func(r int) { //這里改的r是傳值傳進去的r,不會改變要返回的那個r值 r *= 7 }(r) return //空的return }
f1的結果是6。f1是匿名返回值,匿名返回值是在return執行時被聲明,因此defer聲明時,還不能訪問到匿名返回值,defer的修改不會影響到返回值。
f2先給返回值r賦值,r=6,執行defer語句,defer修改r, r = 42,然后函數return。
f3是有名返回值,但是因為r是作為defer的傳參,在聲明defer的時候,就進行參數拷貝傳遞,所以defer只會對defer函數的局部參數有影響,不會影響到調用函數的返回值。
閉包與匿名函數
匿名函數:沒有函數名的函數。函數也是一種類型,一個函數可以賦值給變量
閉包:可以使用另外一個函數作用域中的變量的函數。閉包復制的是原對象指針,這就很容易解釋延遲引用現象。
for i := 0; i <= 3; i++ { defer func() { fmt.Print(i) } } //輸出結果時 3,3,3,3 因為defer函數的i是對for循環i的引用,defer延遲執行,for循環到最后i是3,到defer執行時i就是3 for i := 0; i <= 3; i++ { defer func(i int) { fmt.Print(i) }(i) } //輸出結果時 3,2,1,0 因為defer函數的i是在defer聲明的時候,就當作defer參數傳遞到defer函數中
匿名函數
func main() { /* 匿名函數切片初始化 */ fns := [](func(x int) int){ func(x int) int { return x + 1 }, func(x int) int { return x + 113 }, } println(fns[1](100)) /* 結構體初始化 */ 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
相關推薦
- 2022-07-27 Docker-Compose搭建Spark集群的實現方法_docker
- 2022-07-13 spring-boot2.6.x兼容swagger2問題
- 2022-03-15 request doesn‘t contain a multipart/form-data or m
- 2023-12-16 SpringBoot 配置文件使用@ @取值
- 2022-04-20 C#9.0推出的4個新特性介紹_C#教程
- 2022-11-13 如何修改npm默認源為淘寶源
- 2022-03-13 使用vs2022在.net6中調試帶typescript的靜態頁面_基礎應用
- 2022-07-30 分布式session的問題(使用SpringSession和redis解決)
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支