gin框架使用注意事項


gin框架使用注意事項

本文就說下這段時間我在使用gin框架過程中遇到的問題和要注意的事情。

錯誤處理請求返回要使用c.Abort,不要只是return

當在controller中進行錯誤處理的時候,發現一個錯誤,往往要立即返回,這個時候要記得使用gin.Context.Abort 或者其相關的函數。

類似於:

if err != nil {
		c.AbortWithStatus(500)
		return
	}

這個Abort函數本質是提前結束后續的handler鏈條,(通過將handler的下標索引直接變化為 math.MaxInt8 / 2 )但是前面已經執行過的handler鏈條(包括middleware等)還會繼續返回。

gin的Abort系列的幾個函數為:

func (c *Context) Abort()
func (c *Context) AbortWithStatus(code int)
func (c *Context) AbortWithStatusJSON(code int, jsonObj interface{})
func (c *Context) AbortWithError(code int, err error)

gin的錯誤處理

gin本身默認加載了Recovery()的中間件,所以在不知道如何處理error的時候,可以直接panic出去

如何獲取response的body

需求來源於我要做個gin的中間件,請求進來的時候記錄一下請求參數,請求出去的時候記錄一下請求返回值。在記錄請求返回值的時候,我就需要得到請求的返回內容。但是context里面只有一個結構:

Writer    gin.ResponseWriter

所以這里基本思路就是創建一個Writer,它繼承gin.ResponseWriter。同時,它又有一個byte.buffer來copy一份數據。

// bodyLogWriter是為了記錄返回數據到log中進行了雙寫
type bodyLogWriter struct {
	gin.ResponseWriter
	body *bytes.Buffer
}

func (w bodyLogWriter) Write(b []byte) (int, error) {
	w.body.Write(b)
	return w.ResponseWriter.Write(b)
}

所以,在middleware中就應該這么寫

sTime := time.Now()

blw := &bodyLogWriter{body: bytes.NewBufferString(""), ResponseWriter: c.Writer}
c.Writer = blw

c.Next()

// 請求結束的時候記錄
duration := fmt.Sprintf("%fms", float64(time.Now().Sub(sTime).Nanoseconds()) / 1000000.0)
handler.Tracef(c.Request.Context(), logger.DLTagRequestOut,
	"proc_time=%s||response=%s",
	duration,
	blw.body.String())

主要就是在Next之前吧context.Writer用我們定義的Writer給替換掉,讓它輸出數據的時候寫兩份。

如何獲取所有的請求參數

這個其實和gin框架沒有啥關系,我剛開始使用的時候以為使用request.ParseForm,然后在request.Form中就能得到了。

結果發現當我的Content-type為multipart/form-data的時候,竟然解析不到數據。

追到ParseForm里面發現,http/request.go里面有這么一個部分代碼

case ct == "multipart/form-data":
	// handled by ParseMultipartForm (which is calling us, or should be)
	// TODO(bradfitz): there are too many possible
	// orders to call too many functions here.
	// Clean this up and write more tests.
	// request_test.go contains the start of this,
	// in TestParseMultipartFormOrder and others.
}

我的golang版本是1.11.4。當content-type為multipart/form-data的時候是空的調用的。

當然注釋也寫很清楚了,建議使用ParseMultipartForm

所以獲取http參數的函數我就寫成這個樣子:

// 這個函數只返回json化之后的數據,且不處理錯誤,錯誤就返回空字符串
func getArgs(c *gin.Context) []byte {
	if c.ContentType() == "multipart/form-data" {
		c.Request.ParseMultipartForm(defaultMemory)
	} else {
		c.Request.ParseForm()
	}
	args, _ := json.Marshal(c.Request.Form)
	return args
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM