首頁  >  文章  >  後端開發  >  關於golang中的錯誤處理機制的詳細介紹

關於golang中的錯誤處理機制的詳細介紹

王林
王林原創
2019-12-07 09:36:532741瀏覽

關於golang中的錯誤處理機制的詳細介紹

基礎

錯誤處理應該是工程的一部分,Golang中的error是一個interface類型,如下:

type error interface {
	Error() string
}

凡是實作Error()方法的結構,都可以當作錯誤處理。因此如果函數可能出現錯誤,那麼可以在傳回值的最後,傳回一個錯誤,例如:

func foo() error {
	// ... do something
	return errors.New("foo error")
}

#直接傳回錯誤

直接傳回錯誤,類似於直接傳回字串類型的錯誤,或錯誤碼之類的。字串類型的錯誤,在基礎部分提到了。錯誤碼相當於Linux、C程式中的錯誤碼,一般我們需要自己定義。舉個例子:

package mypkg

type ErrCode int

const (
	ERR1 = 1
	ERR2 = 2
	ERR3 = 3
)

func sub(a, b int) (int, ErrCode) {
	if b < 0 {
		return 0, ERR1
	} else if a < b {
		return 0, Err2
	} else if a < 0 {
		return 0, Err3
	}
	return a - b
}

這種類型的錯誤,編寫簡單,但是有兩個缺陷:

1、外層如果想要使用錯誤碼,則需要引入這個包,容易出現循環引用的情況。

2、如果套件內部修改回傳的錯誤碼類型,則外部使用到錯誤碼的地方,都要進行對應的修改,破壞了封閉性。

對於第一個缺陷,可以使用一個第三方的包,專門存放錯誤碼,這個方式值得商榷。永遠不要透過判斷Error()方法傳回的字串的值,來進行對應的錯誤處理! ! !

傳回自訂類型的錯誤

該方式可以傳回自訂的類型,並透過斷言自訂類型,來進行相關的錯誤處理;自訂類型可以攜帶更多的信息,程式碼實例:

package main

import (
	"errors"
	"fmt"
	"runtime/debug"
)

type MyError struct {
	Inner      error                  // 内粗错误
	Message    string                 // 自定义错误信息
	StackTrace string                 // 堆栈信息
	Misc       map[string]interface{} //其它的一些数据
}

func (myError MyError) Error() string {
	return myError.Message
}

func wrapError(err error, msg string, msgArgs ...interface{}) MyError {
	return MyError{
		Inner:      err,
		Message:    fmt.Sprintf(msg, msgArgs),
		StackTrace: string(debug.Stack()),
		Misc:       make(map[string]interface{}),
	}
}

func Handle(key int) error {
	if key < 0 {
		return wrapError(errors.New("key < 0"), "This is an error test")
	}
	return nil
}

func main() {
	if err := Handle(-1); err != nil {
		if e, ok := err.(MyError); ok {
			fmt.Printf("Inner: %v, Message: %v, StackTrace: %v\n",
				e.Inner, e.Message, e.StackTrace)  // 这里输出对应的数据
		}
	}
}

這種方式處理問題更加方便,但是仍然可能會有包循環引用的問題。

隱藏內部細節的錯誤處理

上述兩種方式,可以適應一些場景,不過都無法解決可能存在循環依賴的問題。為此,我們使用github.com/pkg/errors的套件來解決問題,給出一個程式碼實例。

func New(message string) error

如果有現成的error,我們需要對他進行再次包裝處理,這時候有三個函數可以選擇。

//只附加新的信息
func WithMessage(err error, message string) error
//只附加调用堆栈信息
func WithStack(err error) error
//同时附加堆栈和信息
func Wrap(err error, message string) error

其實上面的包裝,很類似Java的異常包裝,被包裝的error,其實就是Cause,在前面的章節提到錯誤的根本原因,就是這個Cause。所以這個錯誤處理函式庫為我們提供了Cause函數讓我們可以得到最根本的錯誤原因。

func Cause(err error) error {
	type causer interface {
		Cause() error
	}

	for err != nil {
		cause, ok := err.(causer)
		if !ok {
			break
		}
		err = cause.Cause()
	}
	return err
}

使用for迴圈一直找到最根本(最底層)的那個error。

相關文章教學推薦:golang教學

#

以上是關於golang中的錯誤處理機制的詳細介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn