Home  >  Article  >  Backend Development  >  Detailed introduction to the error handling mechanism in golang

Detailed introduction to the error handling mechanism in golang

王林
王林Original
2019-12-07 09:36:532720browse

Detailed introduction to the error handling mechanism in golang

Basics

Error handling should be part of the project. The error in Golang is an interface type, as follows:

type error interface {
	Error() string
}

Any structure that implements the Error() method can be treated as an error. Therefore, if an error may occur in the function, you can return an error at the end of the return value, for example:

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

Return the error directly

Return the error directly, similar to directly Returns an error of string type, or an error code or the like. String type errors were mentioned in the Basics section. The error code is equivalent to the error code in Linux and C programming. Generally, we need to define it ourselves. For example:

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
}

This type of error is simple to write, but it has two flaws:

1. If you want to use error codes in the outer layer, you need to introduce this package, which is easy A circular reference occurs.

2. If the error code type returned is modified internally in the package, corresponding modifications must be made wherever the error code is used externally, destroying the closure.

For the first flaw, you can use a third-party package to specifically store error codes. This method is worthy of discussion. Never judge the value of the string returned by the Error() method to handle the corresponding error! ! !

Return a custom type of error

This method can return a custom type and perform related error handling by asserting the custom type; custom type It can carry more information. Code example:

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

This way of handling the problem is more convenient, but there may still be problems with package circular references.

Error handling to hide internal details

The above two methods can be adapted to some scenarios, but neither can solve the problem of possible circular dependencies. To this end, we use the github.com/pkg/errors package to solve the problem and give a code example.

func New(message string) error

If there is a ready-made error, we need to package it again. At this time, there are three functions to choose from.

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

In fact, the above packaging is very similar to Java's exception packaging. The packaged error is actually Cause. The root cause of the error mentioned in the previous chapter is this Cause. So this error handling library provides us with the Cause function so that we can get the most fundamental cause of the error.

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
}

Use a for loop to find the most fundamental (bottom-level) error.

Recommended related articles and tutorials: golang tutorial

The above is the detailed content of Detailed introduction to the error handling mechanism in golang. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn