Golang?Gin解析JSON請(qǐng)求數(shù)據(jù)避免出現(xiàn)EOF錯(cuò)誤
JSON是前后端交互的重要數(shù)據(jù)類型之一,使用Gin Web框架可以很方便地將HTTP請(qǐng)求報(bào)文中JSON格式的Body數(shù)據(jù)解析到結(jié)構(gòu)體Struct或字典Map數(shù)據(jù)結(jié)構(gòu)中。
環(huán)境
go version go1.14.3 windows/amd64 github.com/gin-gonic/gin v1.6.3
1. 結(jié)論
參考 Fix #216: Enable to call binding multiple times in some formats #1341
使用場(chǎng)景 | 函數(shù) |
---|---|
單次綁定 | ShouldBindJSON > BindJSON |
多次綁定 | ShouldBindBodyWith |
ShouldBindJSON方法是最常用解析JSON數(shù)據(jù)的方法之一,但在重復(fù)調(diào)用的情況下會(huì)出現(xiàn)EOF的報(bào)錯(cuò),這個(gè)原因出在ShouldBindJSON在調(diào)用過一次之后context.request.body.sawEOF的值是false導(dǎo)致,所以如果要多次綁定多個(gè)變量,需要使用ShouldBindBodyWith。
至于為什么單次綁定不優(yōu)選使用BindJSON方法,主要因?yàn)锽indJSON方法會(huì)強(qiáng)制拋出錯(cuò)誤,影響正常流程。
以下為范例:
// 以下是用于存儲(chǔ)JSON數(shù)據(jù)的結(jié)構(gòu)體 type MsgJson struct { Msg string `json:"msg"` } // 單次綁定使用 ShouldBindJSON 方法 func bindExample(c *gin.Context) { // ---> 聲明結(jié)構(gòu)體變量 var a MsgJson // ---> 綁定數(shù)據(jù) if err := c.ShouldBindJSON(&a); err != nil { c.AbortWithStatusJSON( http.StatusInternalServerError, gin.H{"error": err.Error()}) return } // --> 返回 c.JSON(http.StatusOK, gin.H{"msg": "ok"}) return } // 多次綁定優(yōu)先使用 ShouldBindBodyWith 方法 func bindWithRightWay(c *gin.Context) { // ---> 聲明兩個(gè)結(jié)構(gòu)體變量用于存儲(chǔ)JSON數(shù)據(jù) var a, b MsgJson // ---> 第一次解析(注意第二個(gè)參數(shù)是 binding.JSON) if err := c.ShouldBindBodyWith(&a, binding.JSON); err != nil { c.AbortWithStatusJSON( http.StatusInternalServerError, gin.H{"error": err.Error()}) return } // ---> 第二次解析 if err := c.ShouldBindBodyWith(&b, binding.JSON); err != nil { c.AbortWithStatusJSON( http.StatusInternalServerError, gin.H{"error": err.Error()}) return } // ---> 返回 c.JSON(http.StatusOK, gin.H{"msg": "ok"}) return }
2. EOF錯(cuò)誤復(fù)現(xiàn)
EOF錯(cuò)誤出現(xiàn)在第二次使用ShouldBindJSON方法,在多次綁定的情況下,優(yōu)先使用ShouldBindBodyWith,以下為錯(cuò)誤示范:
type MsgJson struct { Msg string `json:"msg"` } func main() { r := gin.Default() r.POST("/v2", bindWithError) _ = r.Run("127.0.0.1:9001") } func bindWithError(c *gin.Context) { var a, b MsgJson if err := c.ShouldBindJSON(&a); err != nil {....} // ---> 注意,這里會(huì)出現(xiàn)EOF報(bào)錯(cuò) if err := c.ShouldBindJSON(&b); err != nil {....} ....... return }
Postman測(cè)試結(jié)果:
Goland斷點(diǎn)調(diào)試:
3. ShouldBindBodyWith 源碼分析
ShouldBindBodyWith和ShouldBindWith很像,但它保存了requests的Body到上下文,允許Body被繼續(xù)調(diào)用。
注意:這個(gè)方法會(huì)先讀取Body然后綁定,如果只綁定一次,建議使用ShouldBindWith來獲得更好的性能(因?yàn)楹笳邥?huì)直接讀取并寫到指定變量,而沒有寫入上下文)。
func (c *Context) ShouldBindBodyWith(obj interface{}, bb binding.BindingBody) (err error) { var body []byte // ---> 先看上下文是否已經(jīng)有Body的Bytes數(shù)據(jù) if cb, ok := c.Get(BodyBytesKey); ok { if cbb, ok := cb.([]byte); ok { body = cbb } } // ---> 如果Body不為空的情況下,讀取Body數(shù)據(jù)并寫入上下文 if body == nil { body, err = ioutil.ReadAll(c.Request.Body) if err != nil { return err } c.Set(BodyBytesKey, body) } return bb.BindBody(body, obj) }
流程圖
以上就是Golang Gin解析JSON請(qǐng)求數(shù)據(jù)避免出現(xiàn)EOF錯(cuò)誤的詳細(xì)內(nèi)容,更多關(guān)于Golang Gin解析JSON請(qǐng)求數(shù)據(jù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- goland 搭建 gin 框架的步驟詳解
- Go Web框架gin的入門教程
- Golang Gin框架實(shí)現(xiàn)文件下載功能的示例代碼
- golang gin框架獲取參數(shù)的操作
- golang gin 框架 異步同步 goroutine 并發(fā)操作
- 用go gin server來做文件上傳服務(wù)
- 基于Go和Gin的環(huán)境配置方法
- golang中g(shù)in框架接入jwt使用token驗(yàn)證身份
- golang?gin框架實(shí)現(xiàn)大文件的流式上傳功能
- golang 網(wǎng)絡(luò)框架之gin的使用方法
- 加速開發(fā):使用Go語言和Gin框架構(gòu)建Web項(xiàng)目的利器
相關(guān)文章
Go1.18?新特性之多模塊Multi-Module工作區(qū)模式
這篇文章主要介紹了Go1.18?新特性之多模塊Multi-Module工作區(qū)模式,在 Go 1.18之前,建議使用依賴模塊中的 replace 指令來處理這個(gè)問題,從 Go 1.18開始引入了一種同時(shí)處理多個(gè)模塊的新方法,通過案例給大家詳細(xì)介紹,感興趣的朋友一起看看吧2022-04-04Go語言json編碼駝峰轉(zhuǎn)下劃線、下劃線轉(zhuǎn)駝峰的實(shí)現(xiàn)
這篇文章主要介紹了Go語言json編碼駝峰轉(zhuǎn)下劃線、下劃線轉(zhuǎn)駝峰的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06golang實(shí)現(xiàn)并發(fā)數(shù)控制的方法
下面小編就為大家分享一篇golang實(shí)現(xiàn)并發(fā)數(shù)控制的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2017-12-12go語言LeetCode題解999可以被一步捕獲的棋子數(shù)
這篇文章主要為大家介紹了go語言LeetCode題解999可以被一步捕獲的棋子數(shù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12Go?json自定義Unmarshal避免判斷nil示例詳解
這篇文章主要為大家介紹了Go?json自定義Unmarshal避免判斷nil示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06詳解golang中發(fā)送http請(qǐng)求的幾種常見情況
這篇文章主要介紹了詳解golang中發(fā)送http請(qǐng)求的幾種常見情況,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12go實(shí)現(xiàn)自動(dòng)復(fù)制U盤小工具demo
這篇文章主要為大家介紹了go實(shí)現(xiàn)自動(dòng)復(fù)制U盤小工具demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12