Golang實(shí)踐之Error創(chuàng)建和處理詳解
error 基本概念
type error interface{
Error() string
}Golang 中 error類型是一個(gè)具有單個(gè)方法的接口,其內(nèi)置方法是返回描述錯(cuò)誤的字符串。Go 語言創(chuàng)始人覺得異常機(jī)制會(huì)導(dǎo)致控制流程混亂,降低代碼的可讀性,所以期望異常是一種可預(yù)知的。所以在使用時(shí)應(yīng)當(dāng)適當(dāng)?shù)姆祷?error ,然后調(diào)用方就可以更明確知道錯(cuò)誤,進(jìn)而再處理異常。同樣也說明了開發(fā)人員在 coding 時(shí)要能識別和預(yù)測可能發(fā)生錯(cuò)誤,再進(jìn)行處理,而不是忽略錯(cuò)誤,
panic 和 recover
但可能也會(huì)出現(xiàn)一些我們無法預(yù)料的錯(cuò)誤情況。比較嚴(yán)重的程序錯(cuò)誤導(dǎo)致發(fā)生 panic 就會(huì)使程序結(jié)束,所以它又提供一個(gè) recover 來捕獲 panic ,以便發(fā)生panic時(shí)能夠重新執(zhí)行啟動(dòng)程序。
defer func() {
if r := recover(); r != nil {
fmt.Println("重新啟動(dòng)程序:", r)
}
}()recover 函數(shù)最好在主函數(shù)中且必須在 defer 語句總使用,為了保證發(fā)生 panic 時(shí)被調(diào)用,如果沒有panic時(shí)recover 函數(shù)將會(huì)返回 nil。
對于panic 的錯(cuò)誤,應(yīng)當(dāng)全面記錄錯(cuò)誤信息,這樣才有利于排查問題。對于一些比較重要的服務(wù)應(yīng)當(dāng)適當(dāng)增加報(bào)警機(jī)制以通知相關(guān)團(tuán)隊(duì)或人員。
創(chuàng)建錯(cuò)誤
// 方式1:使用 fmt.Errorof("")
func div(x, y int)(int,error){
if y==0 {
return 0,fmt.Errorof("除數(shù) %d 不能為0",y)
}
return x/y, nil
}
// 方式2: 使用errors.New("")
ErrDivByZero := errors.New("除數(shù)不能為0")
return 0,ErrDivByZero
// 方式3:使用 errors.Wrap(err, "除數(shù)不能為0")
return 0,errors.Wrap(err, "除數(shù)不能為0")方式1中 fmt.Errorf 函數(shù)允許使用格式化字符串創(chuàng)建新錯(cuò)誤。
errors.Wrap 函數(shù)允許使用上下文包裝error,使用場景:當(dāng)函數(shù)調(diào)用另一個(gè)方法時(shí)遇到的錯(cuò)誤而導(dǎo)致無法完成業(yè)務(wù)流程,那可能需要從函數(shù)返回錯(cuò)誤。使用 errors.Wrap 函數(shù)需要注意:因其除了錯(cuò)誤信息外還附加了堆棧信息,所以不能在程序中大量使用。
以上3種可以很簡單方便的創(chuàng)建錯(cuò)誤。當(dāng)然支持自定義錯(cuò)誤類型,通過創(chuàng)建實(shí)現(xiàn) error 接口的新類型。例如:
// 方式4: 自定義錯(cuò)誤類型
type MathCalError struct {
message string
}
// 實(shí)現(xiàn) Error 方法
func (e *MathCalError) Error() string {
return e.message
}
func div(x, y int) (int, error) {
if y == 0 {
return 0, &MathCalError{"除數(shù)不能為 0"}
}
return x / y, nil
}處理錯(cuò)誤
根據(jù)遇到到場景,基本對于錯(cuò)誤的處理大致有下面五種情況:
- 忽略錯(cuò)誤:調(diào)用方對于發(fā)生錯(cuò)誤覺得沒有任何影響,那么可以不接收直接忽略
- 記錄錯(cuò)誤并繼續(xù)執(zhí)行:調(diào)用方覺得錯(cuò)誤無影響但需要進(jìn)行記錄,可以接受記錄
- 傳遞錯(cuò)誤:繼續(xù)傳遞錯(cuò)誤。
- 錯(cuò)誤重試:某功能錯(cuò)誤需要再重試,如請求第三方接口超時(shí)時(shí)想再重試。設(shè)置重試次數(shù)限制,以防止錯(cuò)誤持續(xù)存在時(shí)出現(xiàn)無限循環(huán)。
- 嚴(yán)重錯(cuò)誤終止程序:若有些錯(cuò)誤期望終止程序,那直接 panic 處理。
// 忽略錯(cuò)誤
result,_ := getUser()
// 記錄錯(cuò)誤
result,err := getUser();err!=nil{
log,writerInfo("something error", err.Error())
}
// 傳遞錯(cuò)誤
result,err := getUser();err!=nil{
return err
}
// 錯(cuò)誤重試
retryCount := 0
maxRetryCount := 3
for {
result,err := getUser();
if err!=nil{
return err
if retryCount >= maxRetryCount{
return err
}
}
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(time.Duration(retryCount) * time.Second):
retryCount++
continue
}
}
//錯(cuò)誤后直接 panic
if err := getUser(); err != nil {
panic("something wrong")
}項(xiàng)目中使用 Error 的方案
方案一 :定義 ErrorMessage 包
項(xiàng)目中可以定義一個(gè)含有所有錯(cuò)誤信息的包,然后在使用時(shí)直接引用。
package errorMsg
import "errors"
var UndefinedError = errors.New("未定義")
var InvalidateParamsError = errors.New("不合法參數(shù)")
// main 函數(shù)中使用
func getUser() error {
return errorMsg.UndefinedError
}方案二:自定義 error 類型
type ParamNotFound NotFound
type ValueNotFound NotFound
type NotFound struct {
msg string
}
func (n *NotFound) Error() string {
return n.msg
}
// 通過使用 switch 處理不同類型的錯(cuò)誤,
func handleErrors(err error) {
switch v := err.(type) {
case ParamNotFound:
fmt.Printf("ParamNotFound: %v\n", v)
case ValueNotFound:
fmt.Printf("ValueNotFound: %v\n", v)
default:
fmt.Printf("Other error: %v\n", v)
}
}最后
有效的錯(cuò)誤處理對于構(gòu)建可靠的服務(wù)至關(guān)重要,個(gè)人覺得最佳的實(shí)踐是團(tuán)隊(duì)內(nèi)部的統(tǒng)一規(guī)范。沒有最佳實(shí)踐和方案,只有最適合的你的場景的實(shí)踐。
以上就是Golang實(shí)踐之Error創(chuàng)建和處理詳解的詳細(xì)內(nèi)容,更多關(guān)于Golang Error創(chuàng)建和處理的資料請關(guān)注腳本之家其它相關(guān)文章!
- 詳解Golang中創(chuàng)建error的方式總結(jié)與應(yīng)用場景
- Go語言中實(shí)現(xiàn)打印堆棧的errors包的用法詳解
- Go項(xiàng)目分層下的最佳error處理方式分享
- node連接MongoDB數(shù)據(jù)庫錯(cuò)誤:MongoServerSelectionError:?connect?ECONNREFUSED?::1:27017(解決方案)
- django數(shù)據(jù)庫報(bào)錯(cuò)解決匯總:django.db.utils.OperationalError?1045,1049,2003
- Golang錯(cuò)誤處理方式異常與error
相關(guān)文章
Golang中SSE協(xié)議實(shí)現(xiàn)方法
Gin框架通過Server-SentEvents(SSE)實(shí)現(xiàn)流式返回,關(guān)鍵步驟包括設(shè)置正確的響應(yīng)頭、使用Flusher確保數(shù)據(jù)立即發(fā)送、處理客戶端中斷和錯(cuò)誤,本文給大家介紹Golang中SSE協(xié)議實(shí)現(xiàn)方法,感興趣的朋友跟隨小編一起看看吧2026-01-01
golang實(shí)現(xiàn)ping命令的完整代碼
這篇文章給大家介紹了如何使用golang實(shí)現(xiàn)ping命令,文中給大家介紹了完整的實(shí)現(xiàn)代碼,并有詳細(xì)的圖文講解,對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-02-02
Go語言中一定要知道的切片使用注意事項(xiàng)總結(jié)
了解和掌握切片的使用注意事項(xiàng),可以避免意外的程序行為,所以本文就來和大家深入探討一下Go語言切片常見的注意事項(xiàng),希望對大家有所幫助2023-06-06

