久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Go 語言系列30:異常處理

 菜籽愛編程 2022-04-27

上一期我們講了 Go 中的錯誤處理,,這一期講講 Go 中的 異常 處理。錯誤和異常是兩個不同的概念,,非常容易混淆,。錯誤指的是可能出現(xiàn)問題的地方出現(xiàn)了問題;而異常指的是不應該出現(xiàn)問題的地方出現(xiàn)了問題,。

panic

在有些情況,,當程序發(fā)生異常時,無法繼續(xù)運行,。在這種情況下,,我們會使用 panic 來終止程序。當函數(shù)發(fā)生 panic 時,,它會終止運行,,在執(zhí)行完所有的延遲函數(shù)后,程序控制返回到該函數(shù)的調(diào)用方,。這樣的過程會一直持續(xù)下去,,直到當前協(xié)程的所有函數(shù)都返回退出,然后程序會打印出 panic 信息,,接著打印出堆棧跟蹤,,最后程序終止。

我們應該盡可能地使用錯誤,,而不是使用 panicrecover ,。只有當程序不能繼續(xù)運行的時候,才應該使用 panicrecover 機制,。

panic 有兩個合理的用例:

  • 發(fā)生了一個不能恢復的錯誤,,此時程序不能繼續(xù)運行。一個例子就是 web 服務器無法綁定所要求的端口,。在這種情況下,,就應該使用 panic ,因為如果不能綁定端口,,啥也做不了,。
  • 發(fā)生了一個編程上的錯誤。假如我們有一個接收指針參數(shù)的方法,,而其他人使用 nil 作為參數(shù)調(diào)用了它,。在這種情況下,,我們可以使用 panic ,因為這是一個編程錯誤:用 nil 參數(shù)調(diào)用了一個只能接收合法指針的方法,。

觸發(fā) panic

下面是內(nèi)建函數(shù) panic 的簽名:

func panic(v interface{})

當程序終止時,,會打印傳入 panic 的參數(shù)。

package main

func main() {
 panic("runtime error")
}

運行上面的程序,,會打印出傳入 panic 函數(shù)的信息,,并打印出堆棧跟蹤:

panic: runtime error

goroutine 1 [running]:
main.main()
 (...)/main.go:4 +0x27


發(fā)生 panic 時的 defer

上面已經(jīng)提到了,當函數(shù)發(fā)生 panic 時,,它會終止運行,,在執(zhí)行完所有的延遲函數(shù)后,程序控制返回到該函數(shù)的調(diào)用方,。這樣的過程會一直持續(xù)下去,,直到當前協(xié)程的所有函數(shù)都返回退出,然后程序會打印出 panic 信息,,接著打印出堆棧跟蹤,,最后程序終止。下面通過一個簡單的例子看看是不是這樣:

package main

import "fmt"

func myTest() {
 defer fmt.Println("defer in myTest")
 panic("runtime error")
}
func main() {
 defer fmt.Println("defer in main")
 myTest()
}

運行該程序后輸出如下:

defer in myTest
defer in main
panic: runtime error

goroutine 1 [running]:
main.myTest()
 (...)/main.go:7 +0x73
main.main()
 (...)/main.go:11 +0x70


recover

recover 是一個內(nèi)建函數(shù),,用于重新獲得 panic 協(xié)程的控制,。下面是內(nèi)建函數(shù) recover 的簽名:

func recover() interface{}

recover 必須在 defer 函數(shù)中才能生效,在其他作用域下,,它是不工作的,。在延遲函數(shù)內(nèi)調(diào)用 recover ,可以取到 panic 的錯誤信息,,并且停止 panic 續(xù)發(fā)事件,,程序運行恢復正常。下面是網(wǎng)上找的一個例子:

package main

import "fmt"

func myTest(x int) {
 defer func() {
  // recover() 可以將捕獲到的 panic 信息打印
  if err := recover(); err != nil {
   fmt.Println(err)
  }
 }()
 var array [10]int
 array[x] = 1
}
func main() {
 // 故意制造數(shù)組越界 觸發(fā) panic
 myTest(20)
 // 如果能執(zhí)行到這句 說明 panic 被捕獲了
 // 后續(xù)的程序能繼續(xù)運行
 fmt.Println("everything is ok")
}

雖然該程序觸發(fā)了 panic ,,但由于我們使用了 recover() 捕獲了 panic 異常,,并輸出 panic 信息,即使 panic 會導致整個程序退出,,但在退出前,,有 defer 延遲函數(shù),還是得執(zhí)行完 defer ,。然后程序還會繼續(xù)執(zhí)行下去:

runtime error: index out of range [20] with length 10
everything is ok

這里要注意一點,,只有在相同的協(xié)程中調(diào)用 recover 才管用, recover 不能恢復一個不同協(xié)程的 panic ,。

package main

import (
 "fmt"
 "time"
)

func main() {
 // 這個 defer 并不會執(zhí)行
 defer fmt.Println("in main")
 go func() {
  defer println("in goroutine")
  panic("")
 }()
 time.Sleep(time.Second)
}

運行后輸出如下:

in goroutine
panic: 

goroutine 19 [running]:
main.main.func1()
 (...)/main.go:13 +0x7b
created by main.main
 (...)/main.go:11 +0x79

參考文獻:

[1] Alan A. A. Donovan; Brian W. Kernighan, Go 程序設計語言, Translated by 李道兵, 高博, 龐向才, 金鑫鑫 and 林齊斌, 機械工業(yè)出版社, 2017.

??周一至周五更新,,期待你的關(guān)注??

    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多