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

聊聊Go 語言的錯誤處理

開發(fā) 后端
在 go 語言中,有一個預(yù)定義的接口:error,該接口自帶一個 Error() 方法,調(diào)用該方法會返回一個字符串。

[[396764]]

構(gòu)造 error

在 go 語言中,有一個預(yù)定義的接口:error,該接口自帶一個 Error() 方法,調(diào)用該方法會返回一個字符串。

  1. type error interface { 
  2.   Error() string 

調(diào)用該方法,會返回當(dāng)前錯誤的具體結(jié)果。一般有下面幾種方式生成 error。

  • errors.New()
  • fmt.Errorf()

errors.New()

調(diào)用 errors.New() 會返回一個 error 類型的結(jié)構(gòu)體,該結(jié)構(gòu)體內(nèi)部會實現(xiàn)一個 Error() 方法, 調(diào)用該方法返回的結(jié)果為調(diào)用 errors.New() 方法時傳入的內(nèi)容。

  1. import ( 
  2.  "errors" 
  3.  "fmt" 
  4.  
  5. func divide(a, b int) (error, int) { 
  6.  if b == 0 { 
  7.     // 被除數(shù)為0,則構(gòu)造一個 error 結(jié)構(gòu)體 
  8.   return errors.New("被除數(shù)不能為0"), 0 
  9.  } 
  10.  var result = a / b 
  11.  return nil, result 
  12.  
  13. func main() { 
  14.  var err error // error 類型數(shù)據(jù)的初始值為 nil,類似于 js 中的 null 
  15.  var result int 
  16.  
  17.  err, result = divide(1, 0) 
  18.  
  19.   if err == nil { 
  20.     // 如果 err 為 nil,說明運行正常 
  21.     fmt.Println("計算結(jié)果", result) 
  22.   } else { 
  23.     // 如果 err 不為 nil,說明運行出錯 
  24.     // 調(diào)用 error 結(jié)構(gòu)體的 Error 方法,輸出錯誤原因 
  25.     fmt.Println("計算出錯", err.Error()) 
  26.   } 

可以看到,上面的代碼中,由于調(diào)用 divide 除法方法時,由于傳入的被除數(shù)為 0。經(jīng)過判斷,會拋出一個由 errors.New 構(gòu)造的 error 類型的結(jié)構(gòu)體。

我們將調(diào)用 error.Error() 方法返回的結(jié)果輸出到控制臺,可以發(fā)現(xiàn)其返回的結(jié)果,就是傳入 New 方法的值。

執(zhí)行結(jié)果如下:

fmt.Errorf()

通過 fmt.Errorf() 方法構(gòu)造的 error 結(jié)構(gòu)體,與調(diào)用 errors.New() 方法的結(jié)果類似。不同的是,fmt.Errorf() 方法會進(jìn)行一次數(shù)據(jù)的格式化。

  1. func divide(a, b int) (error, int) { 
  2.  if b == 0 { 
  3.     // 將參數(shù)進(jìn)行一次格式化,格式化后的字符串放入 error 中 
  4.   return fmt.Errorf("數(shù)據(jù) %d 不合法", b), 0 
  5.  } 
  6.  var result = a / b 
  7.  return nil, result 
  8.  
  9. err, result := divide(1, 0) 
  10. fmt.Println("計算出錯", err.Error()) 

執(zhí)行結(jié)果如下:

panic() 與 recover()

panic()

panic() 相當(dāng)于主動停止程序運行,調(diào)用時 panic() 時,需要傳入中斷原因。調(diào)用后,會在控制臺輸出中斷原因,以及中斷時的調(diào)用堆棧。我們可以改造一下之前的代碼:

  1. func divide(a, b int) (error, int) { 
  2.  if b == 0 { 
  3.     // 如果程序出錯,直接停止運行 
  4.   panic("被除數(shù)不能為0"
  5.  } 
  6.  var result = a / b 
  7.  return nil, result 
  8.  
  9. func main() { 
  10.   err, result := divide(1, 0) 
  11.   fmt.Println("計算出錯", err.Error()) 

在運行到 panic() 處,程序直接中斷,并在控制臺打印出了中斷原因。

panic() 可以理解為,js 程序中的 throw new Error() 的操作。那么,在 go 中有沒有辦法終止 panic() ,也就是類似于 try-catch 的操作,讓程序回到正常的運行邏輯中呢?

recover()

在介紹 recover() 方法之前,還需要介紹一個 go 語言中的另一個關(guān)鍵字:defer。

defer 后的語句會在函數(shù)進(jìn)行 return 操作之前調(diào)用,常用于資源釋放、錯誤捕獲、日志輸出。

  1. func getData(table, sql) { 
  2.   defer 中斷連接() 
  3.   db := 建立連接(table
  4.   data := db.select(sql) 
  5.   return data 

defer 后的語句會被存儲在一個類似于棧的數(shù)據(jù)結(jié)構(gòu)內(nèi),在函數(shù)結(jié)束的時候,被定義的語句按順序出棧,越后面定義的語句越先被調(diào)用。

  1. func divide(a, b intint { 
  2.   defer fmt.Println("除數(shù)為", b) 
  3.   defer fmt.Println("被除數(shù)為", a) 
  4.  
  5.   result := a / b 
  6.   fmt.Println("計算結(jié)果為", result) 
  7.  return result 
  8.  
  9. divide(10, 2) 

上面的代碼中,我們在函數(shù)開始運行的時候,先通過 defer 定義了兩個輸出語句,先輸出除數(shù),后輸出被除數(shù)。

實際的運行結(jié)果是:

  • 先輸出計算結(jié)果;
  • 然后輸出被除數(shù);
  • 最后輸出除數(shù);

這和前面提到的,通過 defer 定義的語句會在函數(shù)結(jié)束的時候,按照出棧的方式進(jìn)行執(zhí)行,先定義的后執(zhí)行。defer 除了會在函數(shù)結(jié)束的時候執(zhí)行,出現(xiàn)異常的的時候也會先走 defer 的邏輯,也就是說,我們在調(diào)用了 panic() 方法后,程序中斷過程中,也會先將 defer 內(nèi)的語句運行一遍。

這里我們重新定義之前的 divide 函數(shù),在執(zhí)行之前加上一個 defer 語句,defer 后面為一個自執(zhí)行函數(shù),該函數(shù)內(nèi)會調(diào)用 recover() 方法。

recover() 方法調(diào)用后,會捕獲到當(dāng)前的 panic() 拋出的異常,并進(jìn)行返回,如果沒有異常,則返回 nil。

  1. func divide(a, b intint { 
  2.   // 中斷之前,調(diào)用 defer 后定義的語句 
  3.  defer func() { 
  4.   if err := recover(); err != nil { 
  5.    fmt.Println("捕獲錯誤", err) 
  6.   } 
  7.  }() 
  8.  
  9.  if b == 0 { 
  10.     // 函數(shù)運行被中斷 
  11.   panic("被除數(shù)不能為0"
  12.   return 0 
  13.  } 
  14.  
  15.  return a / b 
  16.  
  17. result := divide(1, 0) 
  18. fmt.Println("計算結(jié)果", result) 

上面的代碼運行后,我們發(fā)現(xiàn)之前調(diào)用 panic() 中斷的程序被恢復(fù)了,而且后面的計算結(jié)果也正常進(jìn)行輸出了。

這就有點類似于 try-catch 的邏輯了,只是 recover 需要放在 defer 關(guān)鍵詞后的語句中,更像是 catch 和 finally 的結(jié)合。

本文轉(zhuǎn)載自微信公眾號「自然醒的筆記本」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系自然醒的筆記本公眾號。

 

責(zé)任編輯:武曉燕 來源: 自然醒的筆記本
相關(guān)推薦

2014-11-17 10:05:12

Go語言

2021-04-14 07:08:14

Nodejs錯誤處理

2025-03-31 00:29:44

2025-06-06 06:45:54

2021-09-13 07:53:31

Go錯誤處理

2022-09-05 08:55:15

Go2提案語法

2021-09-27 15:33:48

Go 開發(fā)技術(shù)

2020-12-17 06:25:05

Gopanic 模式

2023-10-26 15:49:53

Go日志

2021-09-27 23:28:29

Go多協(xié)程并發(fā)

2021-09-27 10:04:03

Go程序處理

2017-09-22 15:25:40

Go語言其他語言錯誤處理

2023-03-10 08:48:29

2024-03-27 08:18:02

Spring映射HTML

2024-02-28 08:54:57

switchGo錯誤

2022-06-26 23:03:14

Go標(biāo)準(zhǔn)庫語言

2022-07-13 08:53:28

函數(shù)Go語言

2025-02-24 09:30:15

2022-08-01 08:48:39

Go代碼接口

2023-12-26 22:05:53

并發(fā)代碼goroutines
點贊
收藏

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

主站蜘蛛池模板: 国产乱码久久久久久一区二区 | 精品一区二区电影 | 麻豆changesxxx国产 | 天天射天天操天天干 | 巨大荫蒂视频欧美另类大 | 久久精品一区二区 | 国产欧美精品 | 二区中文字幕 | 日韩在线观看一区 | 免费观看av网站 | 中文字幕99| 国产一区二区三区在线 | 中文字幕亚洲一区二区va在线 | 国产成在线观看免费视频 | 狠狠天天| 日韩久久精品 | 91伊人网| 精品国产乱码久久久久久果冻传媒 | 一级黄色片一级黄色片 | 久久久精品影院 | 久久久一区二区 | 日韩福利 | 久久毛片网站 | 欧美一区二区激情三区 | 国产成人午夜精品影院游乐网 | 久久伊人精品一区二区三区 | 综合激情久久 | 亚洲一区二区三 | 日韩黄 | 91麻豆精品国产91久久久资源速度 | 综合成人在线 | av一区二区三区 | 久草免费视 | 欧美激情精品久久久久久 | 久久综合久久综合久久 | 99精品久久 | 综合色播 | 国产精品久久久久国产a级 欧美日韩国产免费 | 欧美精品一区二区在线观看 | av毛片免费 | 成人在线视频一区 |