This is a creation in Article, where the information may have evolved or changed.
Error and Panic
Error: Predictable errors
Panic: Unforeseen anomalies
Panic processing
Handling Exceptions by Panic,defer,recover
The following example code, when an HTTP link to come, Golang will call the serve function, the serve function will parse the HTTP protocol, and then hand over to the upper handler processing, if the upper handler throws an exception, Will be captured by the recover function inside the defer to print out the current stack information so that an exception to an HTTP request causes the entire program to crash.
func (c *conn)serve() { defer func() { if err := recover(); err != nil { const size = 64 << 10 buf := make([]byte, size) buf = buf[:runtime.Stack(buf, false)] fmt.Printlf("http: panic serving %v: %v\n%s", c.remoteAddr, err, buf) } }() w := c.readRequest()
Error handling
Centralized handling of errors in defer
func demo() { var err error defer func() { if err != nil { // 处理发生的错误,打印日志等信息 return } } err = func1() if err != nil { return } err = func2() if err != nil { return }
all-or-nothing check
If there are multiple small tasks in a complete task, we do not need to perform each small task to check for errors, we can judge the execution of the whole task after all the small tasks are done.
//冗长的代码,满篇重复的 if err != nil _, err = fd.Write(p0[a:b])if err != nil { return err}_, err = fd.Write(p1[c:d])if err != nil { return err}_, err = fd.Write(p2[e:f])if err != nil { return err}// and so on
We can simplify the code like this
type errWriter struct { w io.Writer err error}func (ew *errWriter) write(buf []byte) { if ew.err != nil { return } _, ew.err = ew.w.Write(buf)}ew := &errWriter{w: fd}ew.write(p0[a:b])ew.write(p1[c:d])ew.write(p2[e:f])// 只需要在最后检查一次if ew.err != nil { return ew.err}
One obvious problem with this approach is that we don't know if the whole task is going to be an error in the execution of a small task, which is not appropriate if we need to focus on the progress of each small task.
Error context
Error is an interface where any type that implements the error () function satisfies the interface, errors. New () actually returns a errorstring type that contains only a string string, with no contextual information about the error, and when we throw the error up, we do it uniformly at the top, You can only output a single string of information without knowing where the error occurred and under what circumstances.
type error interface { Error() string}type errorString struct { s string}func (e *errorString) Error() string { return e.s}func New(text string) error { return &errorString{text}}
Since error is an interface, we can also implement a type to satisfy the interface, and record the error file, function, stack and other information, more convenient to find the wrong.
Package Stackerrimport ("FMT" "Runtime" "strings") type Stackerr struct {Filename string callingmetho D String Line int errormessage string StackTrace string}func New (Err interface{}) *stackerr {var Errmessage string switch T: = Err. (type) {Case *stackerr:return t case string:errmessage = t case error:errmessage = T.error () Default:errmessage = FMT. Sprintf ("%v", T)} Stackerr: = &stackerr{} Stackerr.errormessage = Errmessage _, file, line, OK: = Runtime . Caller (1) If OK {stackerr.line = line components: = Strings. Split (file, "/") Stackerr.filename = components[(len (components)-1)]} Const SIZE = 1 << buf: = Make ([]byte, size) N: = runtime. Stack (buf, false) Stackerr.stacktrace = string (Buf[:n]) return Stackerr}func (this *stackerr) Error () string {RE Turn this. Errormessage}func (This *stackerr) Stack () string {return FMT.sprintf ("{%s:%d}%s\nstack info:\n%s", this. Filename, this. Line, this. ErrorMessage, this. StackTrace)}func (this *stackerr) Detail () string {return FMT. Sprintf ("{%s:%d}%s", this.) Filename, this. Line, this. ErrorMessage)}
Third-party Error library recommendations
The github.com/pkg/errors is an error library that provides a log context wrapper that makes it easy to add additional information to the error, record stack information, and so on. Refer to GitHub or source code for detailed instructions.