成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Go語言中使用Defer幾個場景

開發(fā) 前端
在Go語言中, panic用于拋出異常, recover用于捕獲異常. recover只能在defer語句中使用, 直接調(diào)用recover是無效的.

關(guān)于 defer 的詳細介紹請參考: Defer, Panic, and Recover .

C++ 中模擬的 defer 實現(xiàn)請參考: C++版的defer語句

1. 簡化資源的回收

這是最常見的 defer 用法. 比如:

  1. mu.Lock()  
  2. defer mu.Unlock() 

當(dāng)然, defer 也有一定的開銷, 也有為了節(jié)省性能而回避使用的 defer 的:

  1. mu.Lock()  
  2. count++  
  3. mu.Unlock() 

從簡化資源的釋放角度看, defer 類似一個語法糖, 好像不是必須的.

2. panic異常的捕獲

defer 除了用于簡化資源的釋放外, 還是Go語言異常框架的一個組成部分.

Go語言中, panic用于拋出異常, recover用于捕獲異常. recover只能在defer語句中使用, 直接調(diào)用recover是無效的.

比如:

  1. func main() {  
  2.     f()  
  3.     fmt.Println("Returned normally from f.")  
  4. }  
  5.  
  6. func f() {  
  7.     defer func() {  
  8.         if r := recover(); r != nil {  
  9.             fmt.Println("Recovered in f", r)  
  10.         }  
  11.     }()  
  12.     fmt.Println("Calling g.")  
  13.     g()  
  14.     fmt.Println("Returned normally from g.")  
  15. }  
  16.  
  17. func g() {  
  18.     panic("ERROR")  

因此, 如果要捕獲Go語言中函數(shù)的異常, 就離不開defer語句了.

3. 修改返回值

defer 除了用于配合 recover, 用于捕獲 panic 異常外, 還可以用于在 return 之后修改函數(shù)的返回值.

比如:

  1. func doubleSum(a, b int) (sum int) {  
  2.     defer func() {  
  3.         sum *= 2 
  4.     }()  
  5.     sum = a + b  

當(dāng)然, 這個特性應(yīng)該只是 defer 的副作用, 具體在什么場景使用就要由開發(fā)者自己決定了.

4. 安全的回收資源

前面第一點提到, defer 最常見的用法是簡化資源的回收. 而且, 從資源回收角度看, defer 只是一個語法糖.

其實, 也不完全是這樣, 特別是在涉及到第二點提到的panic異常等因素導(dǎo)致goroutine提前退出時.

比如, 有一個線程安全的slice修改函數(shù), 為了性能沒有使用defer語句:

  1. func set(mu *sync.Mutex, arr []int, i, v int) {  
  2.     mu.Lock()  
  3.     arr[i] = v  
  4.     mu.Unlock()  

但是, 如果 i >= len(arr)的話, runtime就會拋出切片越界的異常(這里只是舉例, 實際開發(fā)中不應(yīng)該出現(xiàn)切片越界異常). 這樣的話, mu.Unlock() 就沒有機會被執(zhí)行了.

如果用defer的話, 即使出現(xiàn)異常也能保證mu.Unlock()被調(diào)用:

  1. func set(mu *sync.Mutex, arr []int, i, v int) {  
  2.     mu.Lock()  
  3.     defer mu.Unlock()  
  4.     arr[i] = v  

當(dāng)然, Go語言約定異常不會跨越package邊界. 因此, 調(diào)用一般函數(shù)的時候不用擔(dān)心goroutine異常退出的情況.

不過對于一些比較特殊的package, 比如go test依賴的testing包, 包中的t.Fatal就是依賴了Go中類似異常的特性(準(zhǔn)確的說是調(diào)用了runtime.Goexit()).

比如有以下的測試函數(shù)(詳情請參考Issue5746):

  1. func TestFailed(t *testing.T) {  
  2.     var wg sync.WaitGroup  
  3.     for i := 0; i < 2; i++ {  
  4.         wg.Add(1)  
  5.         go func(id int) {  
  6.             // defer wg.Done()  
  7.             t.Fatalf("TestFailed: id = %v\n", id)  
  8.             wg.Done()  
  9.         }(i)  
  10.     }  
  11.     wg.Wait()  

當(dāng)測試失敗的時候, wg.Done()將沒有機會執(zhí)行, 最終導(dǎo)致wg.Wait()死鎖.

對于這個例子, 安全的做法是使用defer語句保證wg.Done()始終會被執(zhí)行.

原文鏈接:http://my.oschina.net/chai2010/blog/140065

責(zé)任編輯:林師授 來源: OSCHINA
相關(guān)推薦

2024-01-07 23:11:16

defer?Go語言

2021-06-07 23:19:44

Golang語言 Defer

2022-09-29 10:01:05

Go編程語言文本文件

2022-11-03 20:38:01

CMD命令Go

2016-02-22 15:02:57

GoRedis連接池

2011-05-25 13:22:05

PHPJSON

2024-04-01 00:02:56

Go語言代碼

2024-05-10 08:36:40

Go語言對象

2023-10-09 07:14:42

panicGo語言

2014-04-09 09:32:24

Go并發(fā)

2024-04-07 11:33:02

Go逃逸分析

2021-07-15 23:18:48

Go語言并發(fā)

2023-12-21 07:09:32

Go語言任務(wù)

2023-01-12 08:52:50

GoroutinesGo語言

2024-08-19 01:10:00

RedisGo代碼

2023-01-30 15:41:10

Channel控制并發(fā)

2023-11-30 08:09:02

Go語言

2022-07-19 12:25:29

Go

2023-07-29 15:03:29

2021-06-08 07:45:44

Go語言優(yōu)化
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 亚洲不卡在线观看 | 草久久久| www.久久久.com| 性国产丰满麻豆videosex | 久久影音先锋 | 欧州一区二区 | 精品视频一区二区三区在线观看 | 国产成人精品一区二三区在线观看 | 国产在线资源 | 女朋友的闺蜜3韩国三级 | 亚洲综合在线视频 | 皇色视频在线 | 精品国产一区二区三区久久久久久 | 精品国产乱码久久久久久影片 | 午夜视频一区 | 日韩久久精品 | 午夜日韩 | 日本一道本| 国产精品亚洲精品久久 | 午夜色播 | 欧美精 | 日本精品在线观看 | 国精产品一区一区三区免费完 | 亚洲国产一区二区视频 | 91网在线播放 | 国产伦精品一区二区三区照片91 | 久久久久国产一区二区三区四区 | 亚洲精品免费在线 | 国产激情在线观看 | 一级毛片大全免费播放 | 久久久精品一区二区 | 成人精品一区二区三区中文字幕 | 国产美女精品 | 成人在线免费观看 | 国产精品福利视频 | 天天爽天天操 | 中文字幕 国产 | 91麻豆精品国产91久久久更新资源速度超快 | 2020国产在线 | 精品一区二区三区在线观看国产 | 亚洲一区二区综合 |