最近写go,路由选择httprouter,现在希望在不修改httprouter源码的前提下,对所有注册的路由handle进行异常捕获。

golang使用panic()产生异常,然后可以recover()来捕获到异常,否则主程序直接宕掉,这是我们不希望看到的。

或者全程检查error,不主动抛出异常。即便这样,可能异常依然不能避免。

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
}

正常的路由表长这样,在C#中相当于对每个请求加try...catch,将业务上代码包裹起来。

golang同理:

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

WrapHandle需要有一个handle类型的参数,同时返回值要能被httprouter接收

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)
}
}

加一个上下文,把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") //通过context从FORM取值,并转换为int64
}

这里加了一个context包,handle的参数也减少到一个,主要是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
} //更多扩展....

好了,先到这里,希望对你有帮助。

【Golang】如何统一处理HTTP请求中的异常捕获的更多相关文章

  1. Swoole 中协程的使用注意事项及协程中的异常捕获

    协程使用注意事项 协程内部禁止使用全局变量,以免发生数据错乱: 协程使用 use 关键字引入外部变量到当前作用域禁止使用引用,以免发生数据错乱: 不能使用类静态变量 Class::$array / 全 ...

  2. 02 flask 请求钩子、异常捕获、上下文、Flask-Script 扩展、jinja2 模板引擎、csrf防范

    一 请求勾子 在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理,比如: 在请求开始时,建立数据库连接: 在请求开始时,根据需求进行权限校验: 在请求结束时,指定数据的交互格式: 为了让每个 ...

  3. [日常] 使用TCPDUMP和Ethereal抓包分析HTTP请求中的异常情况

    在测试功能的过程中,出现这样一种现象.前端js发起ajax请求后,在浏览器的审查元素网络状态中可以看到status为pending,等15秒以后js会把当前超时的请求取消掉,变成了红色的cancel. ...

  4. JAVA 线程中的异常捕获

    在java多线程程序中,所有线程都不允许抛出未捕获的checked exception(比如sleep时的InterruptedException),也就是说各个线程需要自己把自己的checked e ...

  5. C#中的异常捕获机制(try catch finally)

    (转自:http://blog.csdn.net/zevin/article/details/6901489) 一.C#的异常处理所用到关键字try 用于检查发生的异常,并帮助发送任何可能的异常.ca ...

  6. python中的异常捕获怎么用?

    http://www.2cto.com/kf/201301/184121.html http://www.w3cschool.cc/python/python-exceptions.html try: ...

  7. AngularJS 用 Interceptors 来统一处理 HTTP 请求和响应

    Web 开发中,除了数据操作之外,最频繁的就是发起和处理各种 HTTP 请求了,加上 HTTP 请求又是异步的,如果在每个请求中来单独捕获各种常规错误,处理各类自定义错误,那将会有大量的功能类似的代码 ...

  8. 使用domain模块捕获异步回调中的异常

    和其他服务器端语言相比,貌似node.js 对于异常捕捉确实非常困难. 首先你会想到try/catch ,但是在使用过程中我们会发现并没有真正将错误控制在try/catch 语句中. 为什么? 答案是 ...

  9. node.js 使用domain模块捕获异步回调中的异常

    和其他服务器端语言相比,貌似node.js 对于异常捕捉确实非常困难. 首先你会想到try/catch ,但是在使用过程中我们会发现并没有真正将错误控制在try/catch 语句中. 为什么? 答案是 ...

随机推荐

  1. VS2019正式版注册码秘钥

    Visual Studio 2019 EnterpriseBF8Y8-GN2QH-T84XB-QVY3B-RC4DF Visual Studio 2019 ProfessionalNYWVH-HT4X ...

  2. Charles篡改后台数据

    1.打开Charles找到相对应的接口 2.在接口上右键选择Breakpoints打断点. 3.重新请求截断接口,Charles会多弹出一个截断窗口如下图(第一个修改请求的,第二图是修改返回的) 点击 ...

  3. 神经网络训练tricks

    神经网络构建好,训练不出好的效果怎么办?明明说好的拟合任意函数(一般连续)(为什么?可以参考http://neuralnetworksanddeeplearning.com/),说好的足够多的数据(h ...

  4. phpstorm界面不停的indexing,不停的闪烁

    选择 File->Invalidate Caches / Restart...->Invalidate and Restart,就行了!

  5. 网络赛 I题 Max answer 单调栈+线段树

    题目链接:https://nanti.jisuanke.com/t/38228 题意:在给出的序列里面找一个区间,使区间最小值乘以区间和得到的值最大,输出这个最大值. 思路:我们枚举每一个数字,假设是 ...

  6. python中的集合

    在python中,普通集合是可变数据类型 通过以下案例说明: >>> s = {1, 2, 3, 4} >>> id(s) 2108634636808 >&g ...

  7. 创建表结构的sql语句

    1.创建表结构 表名: ODS_PSP_DIS_DAY_CALC create table ODS_PSP_DIS_DAY_CALC ( ID      CHAR(32)  NOT NULL, DIS ...

  8. 分割list,将集合按规定个数分为n个部分。

    /** * 按指定大小,分隔集合,将集合按规定个数分为n个部分 * * @param list * @param len * @return */ public static <T> Li ...

  9. python 数据库mysql、redis及发送邮件

    python 关系型数据库链接使用--mysql import pymysql # 引用mysql模块 # 创建连接,指定数据库的ip地址,账号.密码.端口号.要操作的数据库.字符集coon = py ...

  10. 对js原型及构造函数的相关理解

    一.js中的原型创建(声明)一个函数,浏览器在内存中会创建一个对象.每个函数都默认会有一个属性prototype指向了这个对象,就是说prototype的属性的值就是这个对象.此对象就是该函数的原型对 ...