最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang?Gin解析JSON請(qǐng)求數(shù)據(jù)避免出現(xiàn)EOF錯(cuò)誤

 更新時(shí)間:2022年04月29日 08:33:27   作者:EvaCcino  
這篇文章主要為大家介紹了Golang?Gin?優(yōu)雅地解析JSON請(qǐng)求數(shù)據(jù),避免ShouldBindBodyWith出現(xiàn)EOF錯(cuò)誤的源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

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)文章!

相關(guān)文章

最新評(píng)論

彩票| 榆中县| 游戏| 武义县| 三门峡市| 新兴县| 舟山市| 赞皇县| 新巴尔虎左旗| 重庆市| 利辛县| 桑植县| 乌鲁木齐县| 门源| 四川省| 东乡族自治县| 突泉县| 永昌县| 鸡泽县| 潢川县| 筠连县| 临清市| 甘洛县| 普安县| 卫辉市| 樟树市| 疏附县| 乌鲁木齐县| 罗甸县| 遵义市| 桑日县| 花莲市| 嵩明县| 无棣县| 南皮县| 南昌市| 肥乡县| 乳山市| 镶黄旗| 平安县| 余姚市|