>백엔드 개발 >Golang >golang의 오류 처리 메커니즘에 대한 자세한 소개

golang의 오류 처리 메커니즘에 대한 자세한 소개

王林
王林원래의
2019-12-07 09:36:532788검색

golang의 오류 처리 메커니즘에 대한 자세한 소개

Basics

오류 처리는 프로젝트의 일부여야 합니다. 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
}

这种类型的错误,编写简单,但是有两个缺陷:

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() 메소드의 구조가 오류로 처리될 수 있습니다. 따라서 함수에서 오류가 발생할 수 있는 경우 다음과 같이 반환 값 끝에 오류를 반환할 수 있습니다. 오류 또는 오류 코드 등. 문자열 유형 오류는 기본 섹션에서 언급되었습니다. 오류 코드는 Linux 및 C 프로그래밍의 오류 코드와 동일합니다. 일반적으로 우리는 이를 직접 정의해야 합니다. 예: <p><pre class="brush:php;toolbar:false">//只附加新的信息 func WithMessage(err error, message string) error //只附加调用堆栈信息 func WithStack(err error) error //同时附加堆栈和信息 func Wrap(err error, message string) error</pre></p>이 유형의 오류는 작성하기 쉽지만 두 가지 결함이 있습니다. <p></p>1. 외부 레이어에서 오류 코드를 사용하려면 순환 참조가 발생하기 쉬운 이 패키지를 도입해야 합니다. <p></p>2. 반환된 오류 코드 유형이 패키지 내부에서 수정된 경우 오류 코드가 외부에서 사용되는 모든 위치에서 해당 수정을 수행하여 클로저를 파기해야 합니다. <p><a href="https://www.php.cn/be/go/" target="_blank">첫 번째 결함의 경우 타사 패키지를 사용하여 오류 코드를 구체적으로 저장할 수 있습니다. 해당 오류를 처리하기 위해 Error() 메서드에서 반환된 문자열 값을 판단하지 마세요! ! ! </a></p>🎜사용자 정의 유형의 오류를 반환합니다.🎜🎜🎜이 메서드는 사용자 정의 유형이 더 많은 정보를 전달할 수 있다고 주장하여 사용자 정의 유형을 반환하고 관련 오류 처리를 수행할 수 있습니다. 코드 예: 🎜<pre class="brush:php;toolbar:false">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 }</pre> 🎜이 문제 처리 방법은 다음과 같습니다. 더 편리하지만 패키지 순환 참조에 여전히 문제가 있을 수 있습니다. 🎜🎜🎜내부 세부 정보를 숨기는 오류 처리🎜🎜🎜위의 두 가지 방법은 일부 시나리오에 적용할 수 있지만 둘 다 가능한 순환 종속성 문제를 해결할 수는 없습니다. 이를 위해 <code>github.com/pkg/errors 패키지를 사용하여 문제를 해결하고 코드 예제를 제공합니다. 🎜rrreee🎜기성 오류가 있으면 다시 포장해야 합니다. 이때 선택할 수 있는 기능은 3가지입니다. 🎜rrreee🎜사실 위의 패키징은 Java의 예외 패키징과 매우 유사합니다. 패키징된 오류는 실제로 이전 장에서 언급한 오류의 근본 원인이 바로 이 원인입니다. 따라서 이 오류 처리 라이브러리는 오류의 가장 근본적인 원인을 파악할 수 있도록 Cause 함수를 제공합니다. 🎜rrreee🎜for 루프를 사용하여 가장 근본적인(가장 낮은) 오류를 찾습니다. 🎜🎜추천 관련 기사 및 튜토리얼: 🎜golang 튜토리얼🎜🎜

위 내용은 golang의 오류 처리 메커니즘에 대한 자세한 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.