濮阳杆衣贸易有限公司

主頁 > 知識庫 > Golang try catch與錯(cuò)誤處理的實(shí)現(xiàn)

Golang try catch與錯(cuò)誤處理的實(shí)現(xiàn)

熱門標(biāo)簽:上海企業(yè)外呼系統(tǒng)排名 開通400電話申請流程 400手機(jī)電話免費(fèi)辦理 揚(yáng)州電銷外呼系統(tǒng)軟件 百度地圖標(biāo)注位置網(wǎng)站 武漢百應(yīng)人工智能電銷機(jī)器人 智能語音電銷的機(jī)器人 電腦外呼系統(tǒng)輻射大嗎 如何利用高德地圖標(biāo)注家

Golang try catch

雖然在使用Golang的時(shí)候發(fā)現(xiàn)沒有try catch這種錯(cuò)誤處理機(jī)制但是想一想golang作為一門優(yōu)雅的語言,似乎也是情理之中。因?yàn)樵趈ava中 throws在函數(shù)簽名中有一個(gè)關(guān)鍵字,旨在使異常流程比較簡潔,但是一旦預(yù)期的異常數(shù)量增加,就很難準(zhǔn)確捕捉到具體異常所在。

雖然golang中并不提供try catch的寫法但是零值概念啊等等一些設(shè)計(jì),在加上在panic的時(shí)候還可以使用recover進(jìn)行處理,我覺得還是可以接受的。

在進(jìn)入正題之前我們還是需要新了解一下panic和recover和error

panic

golang新手特別喜歡將panic當(dāng)作exception(我也是這么過來的。。),而這么做會導(dǎo)致panic被濫用。

panic主要使用場景:

  • 發(fā)生嚴(yán)重錯(cuò)誤必須讓進(jìn)行退出,嚴(yán)重的判斷標(biāo)準(zhǔn)是錯(cuò)誤無法恢復(fù)導(dǎo)致程序無法執(zhí)行或繼續(xù)執(zhí)行或者繼續(xù)執(zhí)行也得不到預(yù)定的結(jié)果,另一些場景就是程序啟動需要的初始化數(shù)據(jù)需要在數(shù)據(jù)庫中讀取,這個(gè)時(shí)候數(shù)據(jù)庫無法讀取或者不存在配置項(xiàng)不可讀取,這個(gè)時(shí)候哪怕是執(zhí)行下去程序也是毫無意義的,這個(gè)時(shí)候panic暴露出問題反而是更可取的方式。非嚴(yán)重的錯(cuò)誤比如客戶端不合法的請求參數(shù)返回錯(cuò)誤參數(shù)信息提示即可,讓調(diào)用者自己去處理問題,而不是自己panic掛掉。
  • 快速退出錯(cuò)誤處理。也就是下面需要模擬的try catch的行為。大多數(shù)情況下錯(cuò)誤處理都應(yīng)該使用判斷error的機(jī)制,但是有時(shí)函數(shù)調(diào)用棧很深,逐層返回錯(cuò)誤可能需要寫很多冗余代碼,這個(gè)時(shí)候可以使用panic讓程序的控制流直接跳到頂層的recover來進(jìn)行處理。這種場景需要注意必須在包內(nèi)就要recover。讓panic垮包傳遞可能會導(dǎo)致更復(fù)雜的問題,所以包的到處函數(shù)不應(yīng)該產(chǎn)生panic。

recover

func recover() interface{}

 recover 是一個(gè)內(nèi)建的函數(shù),用于重新獲得 panic 協(xié)程的控制。 只有在延遲函數(shù)的內(nèi)部,調(diào)用 recover 才有用。在延遲函數(shù)內(nèi)調(diào)用 recover,可以取到 panic 的錯(cuò)誤信息,并且停止 panic 續(xù)發(fā)事件(Panicking Sequence),程序運(yùn)行恢復(fù)正常。如果在延遲函數(shù)的外部調(diào)用 recover,就不能停止 panic 續(xù)發(fā)事件。

error

golang中內(nèi)置的錯(cuò)誤類型error是一個(gè)接口,自定義的錯(cuò)誤類型必須實(shí)現(xiàn)error接口,這樣調(diào)用可以通過Error()獲取到具體的錯(cuò)誤信息而不用關(guān)系錯(cuò)誤的具體類型。

// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
 Error() string
}

 很多語言限制函數(shù)只能有一個(gè)返回值,這就顯得尤為寶貴,而golang的多返回值語法糖避免了這種方式帶來的不便,錯(cuò)誤值一般作為返回值列表的最后一個(gè),其他返回值是成功執(zhí)行時(shí)需要返回的信息。也就衍生出了如下判斷:

if err != nil {
    // error handling
} else {
    // normal code
}

雖然這種錯(cuò)誤處理方式代碼寫起來很蛋疼,但是golang風(fēng)格確實(shí)推薦使用此種方式。

預(yù)定義錯(cuò)誤值

var numIsZero = errors.New("num1 is zero")
var numIsNotZero = errors.New("num1 is not zero")
 
func GetInt(num1 int) (int, error) {
 if num1 == 0 {
  return num1, numIsZero
 } else {
  return num1, numIsNotZero
 }
}
 
//比較錯(cuò)誤
func ErrEquals() {
 _, err := GetInt(1)
 if err == numIsNotZero {
   
 }
}

自定義錯(cuò)誤類型

HTTP 表示客戶端的錯(cuò)誤狀態(tài)碼有幾十個(gè)。如果為每種狀態(tài)碼都預(yù)定義相應(yīng)的錯(cuò)誤值,代碼會變得很繁瑣:

var ErrBadRequest = errors.New("status code 400: bad request")
var ErrUnauthorized = errors.New("status code 401: unauthorized")

這種場景下最佳的最法是自定義一種錯(cuò)誤類型,并且至少實(shí)現(xiàn) Error() 方法(滿足 error 定義):

type HTTPError struct {
    Code        int
    Description string
}
 
func (h *HTTPError) Error() string {
    return fmt.Sprintf("status code %d: %s", h.Code, h.Description)
}

這種方式下進(jìn)行等值判斷時(shí)需要轉(zhuǎn)成具體的自定義類型然后取出 Code 字段判斷:

func request() error {
    return HTTPError{404, "not found"}
}
 
func main() {
    err := request()
 
    if err != nil {
        // an error occured
        if err.(*HTTPError).Code == 404 {
            // handle a "not found" error
        } else {
            // handle a different error
        }
    }
 
}

使用 panic和recover模擬 tyr catch  謹(jǐn)慎!

tyr catch 需要謹(jǐn)慎使用,因?yàn)閜anic / recover 和 try / catch 機(jī)制最大的不同在于控制流程上的區(qū)別。try / catch 機(jī)制控制流作用在 try 代碼塊內(nèi),代碼塊執(zhí)行到異常拋出點(diǎn)(throw)時(shí),控制流跳出 try 代碼塊,轉(zhuǎn)到對應(yīng)的 catch 代碼塊,然后繼續(xù)往下執(zhí)行。panic / recover 機(jī)制控制流則作用在整個(gè) goroutine 的調(diào)用棧。當(dāng) goroutine 執(zhí)行到 panic 時(shí),控制流開始在當(dāng)前 goroutine 的調(diào)用棧內(nèi)向上回溯(unwind)并執(zhí)行每個(gè)函數(shù)的 defer 。如果 defer 中遇到 recover 則回溯停止,如果執(zhí)行到 goroutine 最頂層的 defer 還沒有 recover ,運(yùn)行時(shí)就輸出調(diào)用棧信息然后退出。所以如果要使用 recover 避免 panic 導(dǎo)致進(jìn)程掛掉,recover 必須要放到 defer 里。為了避免過于復(fù)雜的代碼,最好不要使用嵌套的 defer ,并且 recover 應(yīng)該直接放到 defer 函數(shù)里直接調(diào)用。

package main
 
import (
 "fmt"
)
 
func main() {
 defer func() {
  if err := recover(); err != nil {
   fmt.Println("error:", err)
  }
 }()
 
 fmt.Println("start")
 panic("Big Error")
 fmt.Println("stop")
}

輸出:

start
error: Big Error

此部分的代碼相當(dāng)于try部分的代碼一旦被panic 后面的代碼就不會被執(zhí)行了,而是跳到 defer部分

       fmt.Println("start")
 panic("Big Error")
 fmt.Println("stop")

 接收到錯(cuò)誤并處理相當(dāng)于catch:

defer func() {
  if err := recover(); err != nil {
   fmt.Println("error:", err)
  }
 }()

注意如果想再次catch需要按照從下往上的循序進(jìn)行異常處理,原因的話了解defer。:

func main() {
 defer func() {
  if err := recover(); err != nil {
   fmt.Println("error:", err)
  }
 }()
 
 defer func() {
  if err := recover(); err != nil {
   fmt.Println("再次panic")
   panic(err)
  }
 }()
 
 fmt.Println("start")
 panic("Big Error")
 fmt.Println("stop")
}
func main() {
 defer func() {
  if err := recover(); err != nil {
   fmt.Println("error:", err)
  }
 }()
 
 defer func() {
  if err := recover(); err != nil {
   fmt.Println("再次panic")
   panic(err)
  }
 }()
 
 defer func() {
  if err := recover(); err != nil {
   fmt.Println("再次panic")
   panic(err)
  }
 }()
 
 defer func() {
  if err := recover(); err != nil {
   fmt.Println("再次panic")
   panic(err)
  }
 }()
 
 fmt.Println("start")
 panic("Big Error")
 fmt.Println("stop")
}

輸出:

start
再次panic
再次panic
再次panic
error: Big Error

到此這篇關(guān)于Golang try catch與錯(cuò)誤處理的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Golang try catch與錯(cuò)誤處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:
  • Golang中重復(fù)錯(cuò)誤處理的優(yōu)化方法
  • Golang巧用defer進(jìn)行錯(cuò)誤處理的方法
  • golang 語言中錯(cuò)誤處理機(jī)制

標(biāo)簽:江西 武漢 張掖 宜賓 黑龍江 新余 延邊 嘉峪關(guān)

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Golang try catch與錯(cuò)誤處理的實(shí)現(xiàn)》,本文關(guān)鍵詞  Golang,try,catch,與,錯(cuò)誤,處理,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《Golang try catch與錯(cuò)誤處理的實(shí)現(xiàn)》相關(guān)的同類信息!
  • 本頁收集關(guān)于Golang try catch與錯(cuò)誤處理的實(shí)現(xiàn)的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    临颍县| 昌都县| 来凤县| 合水县| 文山县| 安陆市| 丹阳市| 安泽县| 民勤县| 开阳县| 江西省| 东城区| 安化县| 平陆县| 贵溪市| 古交市| 新田县| 乌鲁木齐市| 格尔木市| 遵义市| 青铜峡市| 南城县| 大冶市| 赤城县| 浮山县| 大城县| 五台县| 江华| 昭平县| 马山县| 托克托县| 阜康市| 桂东县| 鸡西市| 塘沽区| 仪陇县| 卢湾区| 望城县| 萨嘎县| 金华市| 团风县|