Golang Error Handling enhanced version

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

In order to facilitate the sharing, specifically to copy the blog here =
It is hard to tolerate the fact that the error log is printed everywhere in the code, and I have figured out an elegant way of handling errors. Specially sorted out to share.
Source Address: Https://github.com/mozhata/merr

Demand

    • I want to know where the original error occurred and what the corresponding function call stack was.
    • I want to add some additional information to the error returned by a function, but I want to keep the original error message.
    • You may also need a status code to identify a class of errors
    • I think... Well, I think too much.

That's probably the effect of printing.

E500: err: new errraw err: origin errcall stack: main.warpper    practice/go/example/main.go:18main.main    practice/go/example/main.go:12runtime.main    runtime/proc.go:183runtime.goexit    runtime/asm_amd64.s:2086

(print function included)

func logMerr(err error) {    e := merr.WrapErr(err)    fmt.Printf("E%d: err: %s\nraw err: %s\ncall stack: %s\n",        e.StatusCode,        e.Error(),        e.RawErr(),        e.CallStack(),    )}

Key code

The first thing to do is to get a wrong class

type MErr struct {    Message    string    // 保存自定义的错误信息    StatusCode int       // 错误状态码    rawErr     error     // 保存原始错误信息    stackPC    []uintptr // 保存函数调用栈指针}

And then there are some key ways

func (e *MErr) Error() string {    return e.Message}// RawErr the origin errfunc (e MErr) RawErr() error {    return e.rawErr}// CallStack get function call stackfunc (e MErr) CallStack() string {    frames := runtime.CallersFrames(e.stackPC)    var (        f      runtime.Frame        more   bool        result string        index  int    )    for {        f, more = frames.Next()        if index = strings.Index(f.File, "src"); index != -1 {            // trim GOPATH or GOROOT prifix            f.File = string(f.File[index+4:])        }        result = fmt.Sprintf("%s%s\n\t%s:%d\n", result, f.Function, f.File, f.Line)        if !more {            break        }    }    return result}

CallStack()The method is used to convert the function call stack pointer to a string

There is a missing package method

Maintain Rawerr and update Message if Fmtandargs is not empty//update StatusCode to code if code was not 0//notice:th E returned value is used as error, so, should not return Nilfunc Wraperr (err error, code int, Fmtandargs ... interface{}) *    MERR {msg: = Fmterrmsg (Fmtandargs ...) If Err = = Nil {err = errors. New (MSG)} If E, OK: = Err. (*merr);        OK {if msg! = "" {e.message = msg} if code! = 0 {e.statuscode = code } return e} pcs: = make ([]uintptr, +)//Skip the first 3 invocations count: = Runtime. Callers (3, pcs) e: = &merr{statuscode:code, message:msg, Rawerr:err, STACKPC : Pcs[:count],} if e.message = = "" {E.message = Err. Error ()} return e}//fmterrmsg used to format error Messagefunc fmterrmsg (msgs ... interface{}) string {If Len (m SGS) > 1 {return FMT. Sprintf (Msgs[0]. (    String), Msgs[1:] ...) } If Len (msGS) = = 1 {if V, OK: = Msgs[0]. ( string); OK {return V} if V, OK: = Msgs[0]. (error); OK {return V.error ()}} ' return '}

It can be seen that this method of error handling is mainly fmtErrMsg wrapErr CallStack implemented by these three parts

Next, encapsulate a few handy functions

// WrapErr equal to InternalErr(err)// notice: be careful, the returned value is *MErr, not errorfunc WrapErr(err error, fmtAndArgs ...interface{}) *MErr {    return wrapErr(err, http.StatusInternalServerError, fmtAndArgs...)}// WrapErrWithCode if code is not 0, update StatusCode to code,// if fmtAndArgs is not nil, update the Message according to fmtAndArgs// notice: be careful, the returned value is *MErr, not errorfunc WrapErrWithCode(err error, code int, fmtAndArgs ...interface{}) *MErr {    return wrapErr(err, code, fmtAndArgs...)}// NotFoundErr use http.StatusNotFound as StatusCode to express not found err// if fmtAndArgs is not nil, update the Message according to fmtAndArgsfunc NotFoundErr(err error, fmtAndArgs ...interface{}) error {    return wrapErr(err, http.StatusNotFound, fmtAndArgs...)}

This is basically the whole code. There is not much to explain, the basic look at the code is clear. For more detailed usage, you can view the test file
This is the source address

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.