【Golang】如何统一处理HTTP请求中的异常捕获
最近写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请求中的异常捕获的更多相关文章
- Swoole 中协程的使用注意事项及协程中的异常捕获
协程使用注意事项 协程内部禁止使用全局变量,以免发生数据错乱: 协程使用 use 关键字引入外部变量到当前作用域禁止使用引用,以免发生数据错乱: 不能使用类静态变量 Class::$array / 全 ...
- 02 flask 请求钩子、异常捕获、上下文、Flask-Script 扩展、jinja2 模板引擎、csrf防范
一 请求勾子 在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理,比如: 在请求开始时,建立数据库连接: 在请求开始时,根据需求进行权限校验: 在请求结束时,指定数据的交互格式: 为了让每个 ...
- [日常] 使用TCPDUMP和Ethereal抓包分析HTTP请求中的异常情况
在测试功能的过程中,出现这样一种现象.前端js发起ajax请求后,在浏览器的审查元素网络状态中可以看到status为pending,等15秒以后js会把当前超时的请求取消掉,变成了红色的cancel. ...
- JAVA 线程中的异常捕获
在java多线程程序中,所有线程都不允许抛出未捕获的checked exception(比如sleep时的InterruptedException),也就是说各个线程需要自己把自己的checked e ...
- C#中的异常捕获机制(try catch finally)
(转自:http://blog.csdn.net/zevin/article/details/6901489) 一.C#的异常处理所用到关键字try 用于检查发生的异常,并帮助发送任何可能的异常.ca ...
- python中的异常捕获怎么用?
http://www.2cto.com/kf/201301/184121.html http://www.w3cschool.cc/python/python-exceptions.html try: ...
- AngularJS 用 Interceptors 来统一处理 HTTP 请求和响应
Web 开发中,除了数据操作之外,最频繁的就是发起和处理各种 HTTP 请求了,加上 HTTP 请求又是异步的,如果在每个请求中来单独捕获各种常规错误,处理各类自定义错误,那将会有大量的功能类似的代码 ...
- 使用domain模块捕获异步回调中的异常
和其他服务器端语言相比,貌似node.js 对于异常捕捉确实非常困难. 首先你会想到try/catch ,但是在使用过程中我们会发现并没有真正将错误控制在try/catch 语句中. 为什么? 答案是 ...
- node.js 使用domain模块捕获异步回调中的异常
和其他服务器端语言相比,貌似node.js 对于异常捕捉确实非常困难. 首先你会想到try/catch ,但是在使用过程中我们会发现并没有真正将错误控制在try/catch 语句中. 为什么? 答案是 ...
随机推荐
- JAVA字符串的处理
问题描述: 从键盘数入若干文字,最后输入的一行"end"代表结束标记. 统计该段文字中英文字母的个数 将其中的所有单词the全部改为a,输出结果 将该段文字所有的数字串找出来输出 ...
- 用dockerfile创建jmeter的docker镜像
网上多是创建docker镜像是从jmeter官方下载jmeter的tgz包 今天我们用本地已经下载好的tgz包. 以下是dockerfile FROM java:8 ENV http_proxy &q ...
- [转]一千行 MySQL 学习笔记
原文地址:https://www.cnblogs.com/shockerli/p/1000-plus-line-mysql-notes.html /* 启动MySQL */ net start mys ...
- Linux Apache虚拟主机配置方法
apache 虚拟主机配置 注意: 虚拟主机可以开很多个 虚拟主机配置之后,原来的默认/etc/httpd/httpd.conf中的默认网站就不会生效了 练习: 主机server0 ip:172.25 ...
- Cocos2dx开发之设计模式
cocos2dx的几种常见设计模式 一 单例模式 Cocos2dx中的单例有:CCDirector,CCTextureCache,CCSpriteFrameCache,CCScriptEngineMa ...
- idea使用svn or git
有时候项目开始使用svn 后来切换为git, 配置文件还在,导致有时候默认是svn,配置文件在 .idea --> vcs.xml 中, <mapping directory=" ...
- 15. 3Sum (JAVA)
Given an array nums of n integers, are there elements a, b, cin nums such that a + b + c = 0? Find a ...
- 天坑!c++调用python,遭遇R6034问题
起源: AllMyTube下载核心,是c#组件调用c++dll,在dll中初始化Python运行环境.在工作目录有msvcr90.dll文件时,程序运行会弹出如下错误: R6034. -------- ...
- MAVEN工程相关配置
MAVEN工程插件安装: Name: MavenArchiver Location: https://repo1.maven.org/maven2/.m2e/connectors/m2eclipse- ...
- php 守护进程(Daemon)
守护进程(daemon)是一类在后台运行的特殊进程,用于执行特定的系统任务. 很多守护进程在系统引导的时候启动,并且一直运行直到系统关闭. 守护进程一直在后台运行,脱离终端运行的程序 独立运行的守护进 ...