自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Golang 語言中的 Defer 怎么使用?

開發(fā) 后端
在 Golang 語言中,我們可以在函數(shù)(自定義和部分內(nèi)置)或方法中使用 defer 關(guān)鍵字注冊延遲調(diào)用(一個或多個),多個延遲調(diào)用的執(zhí)行順序是先進(jìn)后出(FILO)。

[[404327]]

 01介紹

在 Golang 語言中,我們可以在函數(shù)(自定義和部分內(nèi)置)或方法中使用 defer 關(guān)鍵字注冊延遲調(diào)用(一個或多個),多個延遲調(diào)用的執(zhí)行順序是先進(jìn)后出(FILO)。并且不會受到函數(shù)執(zhí)行結(jié)束退出,顯式調(diào)用 return 和主動(或被動)觸發(fā) panic 的影響,注冊成功的所有延遲調(diào)用都會被執(zhí)行,除非 defer 注冊在 return 之后或者函數(shù)(或方法)調(diào)用 os.Exit(1)。

defer 注冊多個延遲調(diào)用,執(zhí)行順序是先進(jìn)后出(FILO)。

示例代碼:

  1. func main () { 
  2.  defer func() { 
  3.   fmt.Println("A"
  4.  }() 
  5.  
  6.  defer func() { 
  7.   fmt.Println("B"
  8.  }() 
  9.  
  10.  fmt.Println("main goroutine run over"
  11.  
  12.  // panic("this is a panic example"
  13.  
  14.  // return 

defer 如果定義在 return 之后,它等于 defer 沒有注冊,將不會執(zhí)行。

示例代碼:

  1. func main () { 
  2.  fmt.Println("main"
  3.  return 
  4.  defer func() { 
  5.   fmt.Println("A"
  6.  }() 

defer 所在的函數(shù)或方法中,如果調(diào)用 os.Exit(1),defer 即便注冊,也不會執(zhí)行。

示例代碼:

  1. func main () { 
  2.  defer func() { 
  3.   fmt.Println("A"
  4.  }() 
  5.  fmt.Println("main"
  6.  os.Exit(1) 

defer 必須在函數(shù)和方法中才可以使用,并且 defer 后面必須是函數(shù)(自定義和部分內(nèi)置函數(shù))或方法,defer 函數(shù)的實(shí)參是值拷貝。

示例代碼

  1. func main () { 
  2.  a := 0 
  3.  defer func(num int) { 
  4.   fmt.Println("defer func()", num) 
  5.  }(a) 
  6.  a++ 
  7.  fmt.Println(a) 

02使用場景

使用關(guān)鍵字 defer 注冊的函數(shù)(自定義和部分內(nèi)置)或方法,因?yàn)椴粫艿胶瘮?shù)執(zhí)行結(jié)束,顯式調(diào)用 return 和主動(或被動)觸發(fā) panic 的影響,通常會用于防止忘記釋放資源和捕獲 panic(同一 goroutine 中) 防止應(yīng)用程序崩潰退出的應(yīng)用場景。

示例代碼:

  1. func main () { 
  2.  f, err := os.OpenFile("text.txt", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0755) 
  3.  if err != nil { 
  4.   fmt.Println(err) 
  5.  } 
  6.  defer f.Close() 
  7.  n, err := f.WriteString("this is a text file\t"
  8.  if err != nil { 
  9.   fmt.Println(err) 
  10.  } 
  11.  fmt.Println(n) 

閱讀上面這段代碼,我們使用 defer 延遲調(diào)用釋放資源,防止忘記釋放資源(關(guān)閉文件或解鎖),通常 defer 會放在錯誤檢查之后。

示例代碼:

  1. func main () { 
  2.  defer func() { 
  3.   if err := recover(); err != nil { 
  4.    fmt.Println("this is a panic" ) 
  5.   } 
  6.  }() 
  7.  panic("this is a test panic"
  8.  fmt.Println("main"

閱讀上面這段代碼,我們使用 defer 配合 recover 函數(shù),用于攔截 panic(同一 goroutine 中),防止程序崩潰退出。

03注意事項(xiàng)

雖然使用 defer 具有可以用于防止忘記釋放資源和攔截 panic(同一 goroutine 中)防止應(yīng)用程序崩潰退出等好處。

但是 defer 也有副作用,它會使資源延遲釋放,defer 盡量不要再 for-loop 中使用,并且相比于未使用 defer 調(diào)用的函數(shù)(自定義和部分內(nèi)置)或方法,defer 也有一定的性能損耗,Golang 語言官方也在 golang 1.13 和 golang 1.14 中優(yōu)化了 defer 的性能。

相比于 defer 的性能損耗,defer 帶來的使代碼更加優(yōu)雅、可讀和健壯等優(yōu)勢,我認(rèn)為 defer 綜合來看,利大于弊,它可以給 gopher 們帶來的收益比付出的代價更大。所以,我建議大家盡量使用 defer。

還有一點(diǎn)需要注意的是,我們不要使用 defer 調(diào)用有返回值的自定義函數(shù)或方法,返回值會丟失,可能會給應(yīng)用程序帶來意想不到的錯誤。

04總結(jié)

本文我們介紹了 defer 的執(zhí)行機(jī)制,使用場景和注意事項(xiàng),并且給出了相應(yīng)的示例代碼。通常我們會在 Golang 語言開發(fā)中使用 defer 防止忘記釋放資源(關(guān)閉文件或解鎖)和捕獲 panic(同一 goroutine 中) 防止應(yīng)用程序崩潰退出。

本文轉(zhuǎn)載自微信公眾號「Golang語言開發(fā)?!?,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系Golang語言開發(fā)棧公眾號。

 

責(zé)任編輯:武曉燕 來源: Golang語言開發(fā)棧
相關(guān)推薦

2013-06-25 09:52:32

GoGo語言Go編程

2021-04-28 09:02:48

Golang語言Context

2024-01-07 23:11:16

defer?Go語言

2021-09-13 05:02:49

GogRPC語言

2024-04-01 00:02:56

Go語言代碼

2021-07-12 05:05:59

Golang語言字段

2021-01-29 08:56:13

Golang標(biāo)準(zhǔn)庫函數(shù)

2021-05-07 15:28:03

Kafka客戶端Sarama

2021-06-09 23:36:46

Golang語言版本

2011-05-13 17:25:34

C

2024-05-10 08:36:40

Go語言對象

2021-12-13 01:24:14

語言Golang panic

2021-06-29 23:40:19

Golang語言并發(fā)

2021-10-10 23:02:49

Golang語言代碼

2011-05-25 13:22:05

PHPJSON

2014-04-09 09:32:24

Go并發(fā)

2022-01-04 23:13:57

語言PanicGolang

2021-11-08 23:09:07

Go排序數(shù)據(jù)

2023-10-09 07:14:42

panicGo語言

2021-07-26 11:19:43

微服務(wù)開發(fā)技術(shù)
點(diǎn)贊
收藏

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