How "Golang" handles exception captures in HTTP requests uniformly

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

Recently write Golang project, do not use frame, route selection Httprouter
Now want to implement a requirement: without modifying the Httprouter source code, all registered route handle are caught unexpectedly.

We all know that Golang use panic () to produce an exception, and then you can recover () to catch an exception, or the main program will go straight down, which we do not want to see.
Or the whole process to check the error, do not actively throw an exception. Even so, the exceptions can still be avoided.

Since you want to recover (), but do not want to go inside every handle recover () again, if you have such a demand, the following may be useful to you.

func RegRouters(r *httprouter.Router) {    r.GET("/", Home)    r.GET("/contact", Contact)}func Home(w http.ResponseWriter, r *http.Request, params httprouter.Params) {    defer func() {            if pr := recover(); pr != nil {                fmt.Printf("panic recover: %v\r\n", pr)                debug.PrintStack()            }        }()    //something}func Contact(w http.ResponseWriter, r *http.Request, params httprouter.Params) {    defer func() {            if pr := recover(); pr != nil {                fmt.Printf("panic recover: %v\r\n", pr)                debug.PrintStack()            }        }()    //something}

The normal routing table is this way. In C #, it is equivalent to adding try...catch to each request and wrapping the code on the business.
Maybe you've thought about it, yes, wrap it up like this:

func RegRouters(r *httprouter.Router) {    r.GET("/", WrapHandle(Home))    r.GET("/contact", WrapHandle(Contact))}

What does the Wrap method look like? He needs to have a parameter of type handle, and the return value can be received by Httprouter, directly on the code

func WrapHandle(handle httprouter.Handle) httprouter.Handle {    return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {        defer func() {            if pr := recover(); pr != nil {                fmt.Printf("panic recover: %v\r\n", pr)                debug.PrintStack()            }        }()        handle(w, r, p)    }}

is not very simple ~ Let's change it, add a context, simplify the handle

  func Wraphandle (handle func (CTX *context. Context)) Httprouter. Handle {return func (w http. Responsewriter, R *http. Request, P Httprouter. Params) {defer func () {if PR: = recover (); PR! = nil {fmt. Println ("Panic Recover:%v", PR) Debug. Printstack ()}} () CTX: = Context. Newcontext (W, R, p) handle (CTX)}}func Home (CTX *context. Context) {defer func () {if PR: = recover (); PR! = nil {fmt. Printf ("Panic Recover:%v\r\n", PR) Debug. Printstack ()}} ()//something}func contact (ctx *context. Context) {defer func () {if PR: = recover (); PR! = nil {fmt. Printf ("Panic Recover:%v\r\n", PR) Debug. Printstack ()}} ()//something id = ctx. FormInt64 ("id")//value from form via context and convert to int64}  

See what's the difference? Yes, more than one context package, handle parameters are reduced to one, mainly the context can do more things.

A simple prototype of the request context:

type Context struct {    responseWriter http.ResponseWriter    request        *http.Request    params         httprouter.Params    Data           map[string]interface{}}func NewContext(w http.ResponseWriter, r *http.Request, params httprouter.Params) *Context {    ctx := new(Context)    ctx.responseWriter = w    ctx.request = r    ctx.params = params    ctx.Data = make(map[string]interface{})    return ctx}func (ctx *Context) FormValue(name string) string {    return ctx.request.FormValue(name)}func (ctx *Context) FormInt64(name string) int64 {    value, _ := strconv.ParseInt(ctx.FormValue(name), 10, 64)    return value}//更多扩展....

Well, first come here, hope to help you.

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.