日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
創(chuàng)新互聯(lián)GoFrame教程:GoFrameWEB服務(wù)開發(fā)-異常處理

基本介紹

目前大多數(shù)GOlang的第三方?WebServer?庫均沒有默認(rèn)對?HTTP?請求處理過程中產(chǎn)生的異常進(jìn)行捕獲,輕者錯誤產(chǎn)生后無法記錄到日志造成排查錯困難,重則異常造成進(jìn)程直接崩潰,服務(wù)不可用。

10年積累的成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站經(jīng)驗(yàn),可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先網(wǎng)站制作后付款的網(wǎng)站建設(shè)流程,更有辛集免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

當(dāng)你選擇?GoFrame?,你很幸運(yùn)。裸奔誰都會,但作為一款企業(yè)級的基礎(chǔ)開發(fā)框架,對嚴(yán)謹(jǐn)及安全性的要求大于性能,因此默認(rèn)情況下,執(zhí)行過程中產(chǎn)生的?panic?是有被?Server?自動捕獲的,產(chǎn)生?panic?時當(dāng)前執(zhí)行流程會立即中止,但是絕對不會影響進(jìn)程直接崩潰。

獲取異常錯誤

?HTTP?執(zhí)行流程中產(chǎn)生?panic?異常時,默認(rèn)處理是記錄到?Server?的日志文件中。當(dāng)然,開發(fā)者也可以通過注冊中間件方式手動捕獲,然后自定義相關(guān)的錯誤處理。這一操作其實(shí)在中間件章節(jié)的示例中也有介紹,我們這里來再仔細(xì)說明下。

相關(guān)方法

異常的捕獲我們通過?Request?對象中的?GetError?方法獲取。

開發(fā)者不能通過?recover?方法來捕獲異常,因?yàn)?goframe?框架的?Server?已經(jīng)做了捕獲,并且為保證默認(rèn)情況下異常不會引起進(jìn)程崩潰,因此不會再次往上拋異常。

// GetError returns the error occurs in the procedure of the request.
// It returns nil if there's no error.
func (r *Request) GetError() error

該方法往往使用在流程控制組件中,如后置中間件或者?HOOK?鉤子方法中。

使用示例

我們這里使用一個全局的后置中間件來捕獲異常,當(dāng)異常產(chǎn)生后,捕獲并寫入到指定的日志文件中,返回固定友好的提示信息,避免敏感的報(bào)錯信息暴露給調(diào)用端。

需要注意的是:

  • 即使開發(fā)者有自己捕獲記錄異常錯誤的日志,但是?Server?依舊會打印到?Server?自己的錯誤日志文件中。由開發(fā)者調(diào)用日志接口方法輸出的日志屬于業(yè)務(wù)日志(與業(yè)務(wù)相關(guān)),而?Server?自行管理的日志屬于服務(wù)日志(類似于?nginx?的?error.log?)。
  • 由于?goframe?框架大部分的底層錯誤都包含有錯誤時的堆棧信息,如果對于?error?的具體堆棧信息感興趣(具體調(diào)用鏈、報(bào)錯文件路徑、源碼行號等),可以使用?gerror?來獲取。如果異常包含堆棧信息,默認(rèn)情況下會打印到?Server?的?error?日志文件中。
package main

import (
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
)

func MiddlewareErrorHandler(r *ghttp.Request) {
	r.Middleware.Next()
	if err := r.GetError(); err != nil {
		// 記錄到自定義錯誤日志文件
		g.Log("exception").Error(err)
		//返回固定的友好信息
		r.Response.ClearBuffer()
		r.Response.Writeln("服務(wù)器居然開小差了,請稍后再試吧!")
	}
}

func main() {
	s := g.Server()
	s.Use(MiddlewareErrorHandler)
	s.Group("/api.v2", func(group *ghttp.RouterGroup) {
		group.ALL("/user/list", func(r *ghttp.Request) {
			panic("db error: sql is xxxxxxx")
		})
	})
	s.SetPort(8199)
	s.Run()
}

執(zhí)行后,我們通過?curl?工具來試試吧:

$ curl -v "http://127.0.0.1:8199/api.v2/user/list"
> GET /api.v2/user/list HTTP/1.1
> Host: 127.0.0.1:8199
> User-Agent: curl/7.61.1
> Accept: */*
>
< HTTP/1.1 500 Internal Server Error
< Server: GF HTTP Server
< Date: Sun, 19 Jul 2020 07:44:30 GMT
< Content-Length: 52
< Content-Type: text/plain; charset=utf-8
<
服務(wù)器居然開小差了,請稍后再試吧!

獲取異常堆棧

異常堆棧信息

?WebServer?本身在捕獲異常時,如果拋出的異常信息并不包含堆棧內(nèi)容,那么?WebServer?會自動獲取拋出異常位點(diǎn)(即?panic?的位置)的堆棧并創(chuàng)建一個新的包含該堆棧信息的錯誤對象。我們來看一個示例。

package main

import (
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
)

func MiddlewareErrorHandler(r *ghttp.Request) {
	r.Middleware.Next()
	if err := r.GetError(); err != nil {
		r.Response.ClearBuffer()
		r.Response.Writef("%+v", err)
	}
}

func main() {
	s := g.Server()
	s.Use(MiddlewareErrorHandler)
	s.Group("/api.v2", func(group *ghttp.RouterGroup) {
		group.ALL("/user/list", func(r *ghttp.Request) {
			panic("db error: sql is xxxxxxx")
		})
	})
	s.SetPort(8199)
	s.Run()
}

可以看到,我們通過?%+v?的格式化打印來獲取異常錯誤中的堆棧信息。執(zhí)行后,我們通過?curl?工具來測試下:

$ curl "http://127.0.0.1:8199/api.v2/user/list"
db error: sql is xxxxxxx
1. db error: sql is xxxxxxx
   1).  main.main.func1.1
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/.example/other/test.go:25
   2).  github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1.8
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_request_middleware.go:111
   3).  github.com/gogf/gf/v2/net/ghttp.niceCallFunc
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_func.go:46
   4).  github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_request_middleware.go:110
   5).  github.com/gogf/gf/v2/util/gutil.TryCatch
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/util/gutil/gutil.go:46
   6).  github.com/gogf/gf/v2/net/ghttp.(*middleware).Next
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_request_middleware.go:47
   7).  main.MiddlewareErrorHandler
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/.example/other/test.go:10
   8).  github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1.9
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_request_middleware.go:117
   9).  github.com/gogf/gf/v2/net/ghttp.niceCallFunc
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_func.go:46
   10). github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_request_middleware.go:116
   11). github.com/gogf/gf/v2/util/gutil.TryCatch
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/util/gutil/gutil.go:46
   12). github.com/gogf/gf/v2/net/ghttp.(*middleware).Next
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_request_middleware.go:47
   13). github.com/gogf/gf/v2/net/ghttp.(*Server).ServeHTTP
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_server_handler.go:122

錯誤堆棧信息

如果拋出的異常是一個通過?gerror?組件的錯誤對象,或者實(shí)現(xiàn)堆棧打印接口的錯誤對象,由于該異常的錯誤對象已經(jīng)包含了詳細(xì)的堆棧信息,那么?WebServer?將會直接返回該錯誤對象,不會自動創(chuàng)建錯誤對象。我們來看一個示例。

package main

import (
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
)

func MiddlewareErrorHandler(r *ghttp.Request) {
	r.Middleware.Next()
	if err := r.GetError(); err != nil {
		r.Response.ClearBuffer()
		r.Response.Writef("%+v", err)
	}
}

func DbOperation() error {
	// ...
	return gerror.New("DbOperation error: sql is xxxxxxx")
}

func UpdateData() {
	err := DbOperation()
	if err != nil {
		panic(gerror.Wrap(err, "UpdateData error"))
	}
}

func main() {
	s := g.Server()
	s.Use(MiddlewareErrorHandler)
	s.Group("/api.v2", func(group *ghttp.RouterGroup) {
		group.ALL("/user/list", func(r *ghttp.Request) {
			UpdateData()
		})
	})
	s.SetPort(8199)
	s.Run()
}

執(zhí)行后,我們通過?curl?工具來測試下:

$ curl "http://127.0.0.1:8199/api.v2/user/list"
UpdateData error: DbOperation error: sql is xxxxxxx
1. UpdateData error
   1).  main.UpdateData
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/.example/other/test.go:25
   2).  main.main.func1.1
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/.example/other/test.go:34
   3).  github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1.8
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_request_middleware.go:111
   4).  github.com/gogf/gf/v2/net/ghttp.niceCallFunc
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_func.go:46
   5).  github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_request_middleware.go:110
   6).  github.com/gogf/gf/v2/util/gutil.TryCatch
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/util/gutil/gutil.go:46
   7).  github.com/gogf/gf/v2/net/ghttp.(*middleware).Next
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_request_middleware.go:47
   8).  main.MiddlewareErrorHandler
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/.example/other/test.go:10
   9).  github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1.9
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_request_middleware.go:117
   10). github.com/gogf/gf/v2/net/ghttp.niceCallFunc
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_func.go:46
   11). github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_request_middleware.go:116
   12). github.com/gogf/gf/v2/util/gutil.TryCatch
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/util/gutil/gutil.go:46
   13). github.com/gogf/gf/v2/net/ghttp.(*middleware).Next
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_request_middleware.go:47
   14). github.com/gogf/gf/v2/net/ghttp.(*Server).ServeHTTP
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_server_handler.go:122
2. DbOperation error: sql is xxxxxxx
   1).  main.DbOperation
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/.example/other/test.go:19
   2).  main.UpdateData
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/.example/other/test.go:23
   3).  main.main.func1.1
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/.example/other/test.go:34
   4).  github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1.8
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_request_middleware.go:111
   5).  github.com/gogf/gf/v2/net/ghttp.niceCallFunc
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_func.go:46
   6).  github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_request_middleware.go:110
   7).  github.com/gogf/gf/v2/util/gutil.TryCatch
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/util/gutil/gutil.go:46
   8).  github.com/gogf/gf/v2/net/ghttp.(*middleware).Next
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_request_middleware.go:47
   9).  main.MiddlewareErrorHandler
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/.example/other/test.go:10
   10). github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1.9
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_request_middleware.go:117
   11). github.com/gogf/gf/v2/net/ghttp.niceCallFunc
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_func.go:46
   12). github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_request_middleware.go:116
   13). github.com/gogf/gf/v2/util/gutil.TryCatch
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/util/gutil/gutil.go:46
   14). github.com/gogf/gf/v2/net/ghttp.(*middleware).Next
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_request_middleware.go:47
   15). github.com/gogf/gf/v2/net/ghttp.(*Server).ServeHTTP
    	/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/net/ghttp/ghttp_server_handler.go:122


當(dāng)前文章:創(chuàng)新互聯(lián)GoFrame教程:GoFrameWEB服務(wù)開發(fā)-異常處理
瀏覽路徑:http://www.5511xx.com/article/cceiije.html