小強最近在項目中遇到了一個很奇怪的問題:在整改日誌規範時,爲了不影響現有的代碼結構以及改動儘量小的前提下,在調用記日誌的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相關資源。
掃碼關注,精彩內容第一時間推給你