Golang Gin框架的請求參數(shù)處理

在上一章中套耕,我們通過取路由參數(shù)來獲取請求中的參數(shù)构灸,這一章中件已,我們來了解如何在Gin中如何通過各種方法來獲取請求中的數(shù)據(jù)笋额。回憶一下上一講獲取路由參數(shù)的內(nèi)容篷扩。Gin通過 c.Param() 方法獲取路由參數(shù)兄猩,即在路由中定義的變量。例如:

r.GET("/user/:id", func(c *gin.Context) {
    id := c.Param("id")
    c.String(http.StatusOK, "id=%s", id)
})

但如果需要獲取多個參數(shù)鉴未,可以使用 c.Params 屬性枢冤,該屬性是一個數(shù)組,包含了所有的參數(shù)铜秆。例如:

r.GET("/user/:id/:name", func(c *gin.Context) {
    id := c.Param("id")
    name := c.Param("name")
    params := c.Params
    c.String(http.StatusOK, "id=%s, name=%s, params=%v", id, name, params)
})

這里定義了一個路由 /user/:id/:name淹真,通過 c.Params 方法可以獲取所有參數(shù)的值。需要注意的是连茧,c.Params 方法返回的是一個數(shù)組核蘸,其中每個元素是一個 gin.Param 結(jié)構(gòu)體,包含了參數(shù)的鍵值對信息啸驯】驮可以通過 KeyValue 屬性分別獲取鍵和值。

獲取各類請求參數(shù)

除了路由參數(shù)外罚斗,在 Gin 框架中徙鱼,可以使用 c.Query()c.DefaultQuery()针姿、c.PostForm()疆偿、c.DefaultPostForm() 等方法獲取客戶端提交的參數(shù)。這些方法對 GET 和 POST 請求都適用搓幌。

例如,使用 c.Query() 方法可以獲取客戶端通過 URL 提交的參數(shù):

r.GET("/user", func(c *gin.Context) {
    name := c.Query("name")
    age := c.Query("age")
    c.String(http.StatusOK, "name=%s, age=%s", name, age)
})

這里使用 c.Query() 方法獲取了客戶端提交的 nameage 參數(shù)迅箩。

使用 c.DefaultQuery() 方法可以獲取客戶端提交的參數(shù)溉愁,并且在參數(shù)不存在時設(shè)置一個默認值:

r.GET("/user", func(c *gin.Context) {
    name := c.DefaultQuery("name", "guest")
    age := c.DefaultQuery("age", "0")
    c.String(http.StatusOK, "name=%s, age=%s", name, age)
})

這里使用 c.DefaultQuery() 方法獲取了客戶端提交的 nameage 參數(shù),如果這些參數(shù)不存在饲趋,則設(shè)置默認值拐揭。

類似地,使用 c.PostForm()c.DefaultPostForm() 方法可以獲取客戶端通過 POST 請求提交的參數(shù)奕塑。例如:

r.POST("/user", func(c *gin.Context) {
    name := c.PostForm("name")
    age := c.PostForm("age")
    c.String(http.StatusOK, "name=%s, age=%s", name, age)
})

這里使用 c.PostForm() 方法獲取了客戶端提交的 nameage 參數(shù)堂污。

需要注意的是,在使用 c.PostForm()c.DefaultPostForm() 方法獲取客戶端 POST 請求參數(shù)時龄砰,需要在處理請求之前調(diào)用 c.Request.ParseForm() 方法盟猖,以便解析表單參數(shù)讨衣。例如:

r.POST("/user", func(c *gin.Context) {
    c.Request.ParseForm()
    name := c.PostForm("name")
    age := c.PostForm("age")
    c.String(http.StatusOK, "name=%s, age=%s", name, age)
})

另外,Gin 框架還支持通過 c.Bind()式镐、c.ShouldBind()反镇、c.ShouldBindJSON()c.ShouldBindXML() 等方法將客戶端提交的參數(shù)綁定到一個結(jié)構(gòu)體中娘汞。這些方法將自動解析請求體歹茶,并將參數(shù)綁定到指定的結(jié)構(gòu)體中。例如:

type User struct {
    Name string `form:"name" json:"name" xml:"name"`
    Age int `form:"age" json:"age" xml:"age"`
}

r.POST("/user", func(c *gin.Context) {
    var user User
    c.Bind(&user)
    c.String(http.StatusOK, "name=%s, age=%d", user.Name, user.Age)
})

這里定義了一個 User 結(jié)構(gòu)體你弦,使用 c.Bind() 方法將客戶端提交的參數(shù)綁定到該結(jié)構(gòu)體中惊豺,然后使用該結(jié)構(gòu)體處理請求。在結(jié)構(gòu)體中使用 form禽作、json尸昧、xml 等標簽可以指定參數(shù)名,以便正確地綁定參數(shù)领迈。

對于JSON請求處理的特別說明

使用 c.ShouldBindJSON() 方法來處理客戶端提交的 JSON 請求彻磁。該方法可以將 JSON 數(shù)據(jù)綁定到一個指定的結(jié)構(gòu)體中,示例如下:

type User struct {
    Name  string `json:"name"`
    Email string `json:"email"`
}

func main() {
    r := gin.Default()

    r.POST("/user", func(c *gin.Context) {
        var user User

        if err := c.ShouldBindJSON(&user); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }

        c.JSON(http.StatusOK, gin.H{"name": user.Name, "email": user.Email})
    })

    r.Run(":8080")
}

在上面的代碼中狸捅,首先定義了一個 User 結(jié)構(gòu)體衷蜓,用于存儲客戶端提交的 JSON 數(shù)據(jù)。然后尘喝,在路由處理函數(shù)中調(diào)用了 c.ShouldBindJSON() 方法磁浇,將客戶端提交的 JSON 數(shù)據(jù)綁定到 user 變量中。

如果綁定失敗朽褪,則返回一個錯誤信息置吓。如果綁定成功,則返回一個 JSON 響應(yīng)缔赠,將 nameemail 字段的值返回給客戶端衍锚。

需要注意的是,在處理 JSON 請求時嗤堰,必須先將請求體中的數(shù)據(jù)讀取完整才能進行綁定戴质。因此,在調(diào)用 ShouldBindJSON() 方法之前踢匣,需要確保請求體已經(jīng)被完整地讀取告匠。如果請求體沒有被讀取完整,那么該方法會返回一個錯誤信息离唬。

除了上面的方法外后专,還可以使用 c.BindJSON() 方法來處理 JSON 請求,示例如下:

func main() {
    r := gin.Default()

    r.POST("/user", func(c *gin.Context) {
        var user User

        if err := c.BindJSON(&user); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }

        c.JSON(http.StatusOK, gin.H{"name": user.Name, "email": user.Email})
    })

    r.Run(":8080")
}

BindJSON() 方法和 ShouldBindJSON() 方法的區(qū)別在于输莺,BindJSON() 方法會自動根據(jù)請求頭中的 Content-Type 字段來確定請求體的類型戚哎。如果請求體的類型不是 JSON裸诽,則會返回一個錯誤信息。而 ShouldBindJSON() 方法則只會處理請求體為 JSON 的情況建瘫。

需要注意的是崭捍,當(dāng)使用 BindJSON() 方法處理 JSON 請求時,如果請求體不是 JSON 格式啰脚,或者請求體中的數(shù)據(jù)無法綁定到指定的結(jié)構(gòu)體中殷蛇,該方法也會返回一個錯誤信息。因此橄浓,在使用 BindJSON() 方法時粒梦,需要確保請求體中的數(shù)據(jù)是合法的。

各類數(shù)據(jù)格式處理

除了上面的方法外荸实,還可以使用 c.ShouldBind() 方法來處理任意格式的請求數(shù)據(jù)匀们,包括 JSON、XML准给、Form 等格式泄朴。該方法會根據(jù)請求頭中的 Content-Type 字段來自動識別請求的數(shù)據(jù)格式,并將數(shù)據(jù)綁定到指定的結(jié)構(gòu)體中露氮。示例如下:

func main() {
    r := gin.Default()

    r.POST("/user", func(c *gin.Context) {
        var user User

        if err := c.ShouldBind(&user); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }

        c.JSON(http.StatusOK, gin.H{"name": user.Name, "email": user.Email})
    })

    r.Run(":8080")
}

在上面的代碼中祖灰,調(diào)用了 c.ShouldBind() 方法將客戶端提交的數(shù)據(jù)綁定到 user 變量中。如果綁定失敗畔规,則返回一個錯誤信息局扶。如果綁定成功,則返回一個 JSON 響應(yīng)叁扫,將 nameemail 字段的值返回給客戶端三妈。

需要注意的是,當(dāng)使用 ShouldBind() 方法處理請求數(shù)據(jù)時莫绣,需要確保請求體中的數(shù)據(jù)是合法的畴蒲。否則,該方法也會返回一個錯誤信息对室。

其他

除了上述方法外饿凛,Gin 框架還提供了一些其他方法來處理客戶端提交的參數(shù),例如:

  • c.GetHeader():獲取客戶端提交的請求頭信息软驰。
  • c.GetRawData():獲取客戶端提交的請求體信息(原始數(shù)據(jù))。
  • c.Request.FormValue():獲取客戶端提交的表單參數(shù)值心肪。
  • c.Request.PostFormValue():獲取客戶端提交的 POST 請求參數(shù)值锭亏。

以上方法使用起來比較靈活,可以根據(jù)具體的場景選擇合適的方法硬鞍。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末慧瘤,一起剝皮案震驚了整個濱河市戴已,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌锅减,老刑警劉巖糖儡,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異怔匣,居然都是意外死亡握联,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門每瞒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來金闽,“玉大人,你說我怎么就攤上這事剿骨〈撸” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵浓利,是天一觀的道長挤庇。 經(jīng)常有香客問我,道長贷掖,這世上最難降的妖魔是什么嫡秕? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮羽资,結(jié)果婚禮上淘菩,老公的妹妹穿的比我還像新娘。我一直安慰自己屠升,他們只是感情好潮改,可當(dāng)我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著腹暖,像睡著了一般汇在。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上脏答,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天糕殉,我揣著相機與錄音,去河邊找鬼殖告。 笑死阿蝶,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的黄绩。 我是一名探鬼主播羡洁,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼爽丹!你這毒婦竟也來了筑煮?” 一聲冷哼從身側(cè)響起辛蚊,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎真仲,沒想到半個月后袋马,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡秸应,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年虑凛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片灸眼。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡卧檐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出焰宣,到底是詐尸還是另有隱情霉囚,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布匕积,位于F島的核電站盈罐,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏闪唆。R本人自食惡果不足惜盅粪,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望悄蕾。 院中可真熱鬧票顾,春花似錦、人聲如沸帆调。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽番刊。三九已至含鳞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間芹务,已是汗流浹背蝉绷。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留枣抱,地道東北人熔吗。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像佳晶,于是被迫代替她去往敵國和親磁滚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容