ホームページ  >  記事  >  バックエンド開発  >  golang のエラー処理メカニズムの詳細な紹介

golang のエラー処理メカニズムの詳細な紹介

王林
王林オリジナル
2019-12-07 09:36:532625ブラウズ

golang のエラー処理メカニズムの詳細な紹介

基本

エラー処理はプロジェクトの一部である必要があります。Golang のエラーは、次のように 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
}

このタイプのエラーは簡単に記述できますが、次の 2 つの欠陥があります:

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)  // 这里输出对应的数据
		}
	}
}

この問題を処理する方法はより便利ですが、パッケージの循環参照に関しては依然として問題が発生する可能性があります。

内部詳細を非表示にするエラー処理

上記の 2 つの方法は一部のシナリオに適用できますが、どちらも循環依存関係の可能性がある問題を解決できません。この目的のために、github.com/pkg/errors パッケージを使用して問題を解決し、コード例を示します。

func New(message string) error

既製のエラーがある場合は、再度パッケージ化する必要がありますが、このとき選択できる関数は 3 つあります。

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

実際、上記のパッケージ化は Java の例外パッケージ化に非常に似ています。パッケージ化されたエラーは実際には原因です。前の章で説明したエラーの根本原因はこの原因です。したがって、このエラー処理ライブラリは、エラーの最も根本的な原因を取得できるように、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 ループを使用して、最も基本的な (最下位レベルの) エラーを見つけます。

おすすめの関連記事とチュートリアル: golang チュートリアル

以上がgolang のエラー処理メカニズムの詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。