小强最近在项目中遇到了一个很奇怪的问题:在整改日志规范时,为了不影响现有的代码结构以及改动尽量小的前提下,在调用记日志的SDK处将某一个字段值首字母改成大写,代码示例以下:前端
fmt.Println("--------SayHello begin------------") //项目中这里的a实际是做为参数传入,只是可能为空串,不为空串,这样写确定没问题 a := "" b := strings.ToUpper(a[:1]) + a[1:] fmt.Println("b is ", b) fmt.Println("--------SayHello end------------") this.Ctx.Output.Body(this.Ctx.Input.RequestBody)
项目中这里的a变量实际上是做为参数传入,只是可能为空串。a变量不为空串时,这样写确定没问题。可是当为空串时,即""时,就会出问题,在java中,运行的时候确定会报一个“数组下表越界”的异常。小强将工程编译后生成二进制文件,放到服务器上跑,测试修改后的日志是否符合规范,验了一遍,没有问题,而后就将代码提交了。java
以后版本出来测试时发现,有个奇怪的现象:接口不返回任何东西,状态码依然是 200 OK。这让小强很纳闷儿,还好,咱们的小强经验丰富,仍是解决过大bug的人,而后就根据接口走了一遍代码流程,眉头一皱,就知道问题所在了。原来就是a变量有时候传进来是空字符串,致使出现了slice下标越界的panic,说干就干,小强赶忙作了空串的判断逻辑,从新验了一把,问题就解决了。python
小强是爱思考的孩子,不止要解决问题,也要知其因此然。小强在想,出现了panic咋日志里面啥都不打呢,并且还返回200,甚是疑惑。而后就在网上查资料,而后本身又看了beego的源码,就明白了。不得不说,开源就是好啊。golang
原来问题是这样,小强项目中使用的beego版本是1.6.1版。面试
小强查到了beego的错误处理流程:beego经过beego.App.Server.Handler处理全部的HTTP请求,在beego.Run()函数中,这个Handler就被设置为app.Handlers,能够参见beego1.6.1版本app.go的第95行:spring
app.Server.Handler = app.Handlers
而app在一开始就被初始化,能够看app.go中的init()函数,其中调用了NewApp()函数:编程
// NewApp returns a new beego application. func NewApp() *App { cr := NewControllerRegister() app := &App{Handlers: cr, Server: &http.Server{}} return app }
能够看出,把cr赋值给Handler,其实cr是ControllerRegister类型,ControllerRegister类型实现了http.Handler接口,具体实现能够看router.go的第600行ServeHTTP方法。该方法中(第612行)有以下语句:数组
defer p.recoverPanic(context)
golang语言的错误处理机制是,当在某处调用panic(string)后,panic以后的语句将再也不执行,而是经过调用关系逐级退出,在每一级调用处都经过defer处理函数检查是否panic被recover()函数捕获处理,若是没有则继续往上扔panic信息,若是已经被捕获则结束这次panic过程,由捕获panic的函数处继续往下执行。服务器
出现异常会执行recoverPanic方法,该方法中(第864行)有这样的代码段:app
if BConfig.RunMode == DEV { showErr(err, context, stack) }
showErr函数中会对错误进行模板渲染,而小强项目早在现网中投入使用,RunMode为prod,而非dev,因此recover()后不会有错误提示。
当RunMode为prod时:
当RunMode为prod时:
dev模式好歹会返回错误信息:slice bounds out of range
prod模式没有任何提示。下标越界这种问题看似简单,可是真正遇到了有时候也会摸不着头脑。
本公众号免费提供csdn下载服务,海量IT学习资源,若是你准备入IT坑,励志成为优秀的程序猿,那么这些资源很适合你,包括但不限于java、go、python、springcloud、elk、嵌入式 、大数据、面试资料、前端 等资源。同时咱们组建了一个技术交流群,里面有不少大佬,会不定时分享技术文章,若是你想来一块儿学习提升,能够公众号后台回复【2】,免费邀请加技术交流群互相学习提升,会不按期分享编程IT相关资源。
扫码关注,精彩内容第一时间推给你