Gin 框架 -六-: 參數綁定

1. 介紹

Gin框架中參數不但能通過指定key接收, 也可以直接綁定到結構體中, 本篇主要講解怎麼直接綁定到結構體中, 若要查看通過指定key接收,可查看歷史文章 Gin 框架 (五): 參數接收

1.1 綁定方法

Gin提供了Must bind 和 Should bind兩種類型的綁定方法,這兩種類型對應的方法如下:

PBZFfU

a.MustBindWith和ShouldBindWith

Bind*類型的方法是對MustBindWith封裝;Should*類型的方法是對ShouldBindWith的封裝;

1.2 綁定語法

定義被綁定的結構體

type StructName struct {
  Xxx  type  `form:"paramName" binding:"required"`
}

標籤說明:

2. 綁定 uri 參數

通過使用函數BindQueryShouldBindQuery,用來只綁定GET請求中的uri參數,如:/funcName?a=x&b=x中的a和b

2.1 代碼

//-------- main.go ---------------
package main
import (
 "github.com/gin-gonic/gin" // 引入Gin框架
 "go-use/practise" // 代碼示例包
)
func main() {
 engine := gin.Default()
 practise.TestBindQuery(engine)
 _ = engine.Run()
}
//------ go-use/practise/param_bind.go -------
// 定義結構體
type UriParam struct {
 Name  string   `form:"name" binding:"required"`
 Age   int      `form:"age"`
  Home  string   `form:"home"`
}
// 綁定GET(BindQuery和ShouldBindQuery)
func TestBindQuery(engine *gin.Engine) {
 engine.GET("/bindQuery", func(context *gin.Context) {
  bindType := context.Query("type")
  var uriParam UriParam
  var err error
  if bindType == "1" {
   fmt.Println("BindQuery")
   err = context.BindQuery(&uriParam)
  } else {
   fmt.Println("ShouldBindQuery")
   err = context.ShouldBindQuery(&uriParam)
  }
  if err != nil {
   context.JSON(500, gin.H{"error": err.Error()})
   return
  }
  fmt.Printf("uriParam:%+v\n", uriParam)
  context.JSON(200, gin.H{"result": uriParam})
 })
}

2.2 請求

# 參數都傳
➜ curl -X GET http://127.0.0.1:8080/bindQuery?age=24&name=張三&home=北京&type=1
{"result":{"Name":"張三","Age":24,"Home":"北京"}}
➜ curl -X GET http://127.0.0.1:8080/bindQuery?age=24&name=張三&home=北京&type=2
{"result":{"Name":"張三","Age":24,"Home":"北京"}}
# 必填參數name不填時,都會報錯
➜ curl -X GET http://127.0.0.1:8080/bindQuery?age=24&home=北京&type=2
{"error":"Key: 'UriParam.Name' Error:Field validation for 'Name' failed on the 'required' tag"}

3. 綁定 JSON

使用函數BindJSON 和 ShouldBindJSON來綁定提交的JSON參數信息。

3.1 代碼

//-------- main.go ---------------
package main
import (
 "github.com/gin-gonic/gin" // 引入Gin框架
 "go-use/practise" // 代碼示例包
)
func main() {
 engine := gin.Default()
 practise.TestBindJson(engine)
 _ = engine.Run()
}
//------ go-use/practise/param_bind.go -------
// 定義待綁定的JSON結構體
type Param struct {
 Name  string   `json:"name"`
 Age   int      `json:"age"`
 Likes []string `json:"likes"`
}
// 綁定提交的Json數據
func TestBindJson(engine *gin.Engine) {
 engine.POST("/bindJson", func(context *gin.Context) {
  var jsonParam Param
  var err error
  bindType := context.Query("type")
  fmt.Println(bindType)
  if bindType == "1" {
   err = context.BindJSON(&jsonParam)
  } else {
   err = context.ShouldBindJSON(&jsonParam)
  }
  if err != nil {
   context.JSON(500, gin.H{"error": err})
   return
  }
  context.JSON(200, gin.H{"result": jsonParam})
 })
}

3.2 請求

4. 綁定 XML

使用函數BindXML 和 ShouldBindXML來綁定提交的XML參數信息。

4.1 代碼

//-------- main.go ---------------
package main
import (
 "github.com/gin-gonic/gin" // 引入Gin框架
 "go-use/practise" // 代碼示例包
)
func main() {
 engine := gin.Default()
 practise.TestBindXml(engine)
 _ = engine.Run()
}
//------ go-use/practise/param_bind.go -------
// 修改待綁定的JSON結構體,添加XML標籤
type Param struct {
 Name  string   `json:"name" xml:"name"`
 Age   int      `json:"age" xml:"age"`
 Likes []string `json:"likes" xml:"likes"`
}
// 綁定Xml信息
func TestBindXml(engine *gin.Engine) {
 engine.POST("/bindXml", func(context *gin.Context) {
  var param Param
  var err error
  bindType := context.Query("type")
  if bindType == "1" {
   err = context.BindXML(m)
  } else {
   err = context.ShouldBindXML(m)
  }
  if err != nil {
   context.JSON(500, gin.H{"error": err})
   return
  }
  context.JSON(200, gin.H{"result": param})
 })
}

4.2 請求

5. 綁定request.Body

c.Request.Body 不能多次被調用, 第一次綁定之後 c.Request.Body會設置成EOF

5.1 錯誤示例

a. 代碼

//-------- main.go ---------------
package main
import (
 "github.com/gin-gonic/gin" // 引入Gin框架
 "go-use/practise" // 代碼示例包
)
func main() {
 engine := gin.Default()
 practise.TestBindXml(engine)
 _ = engine.Run()
}
//------ go-use/practise/param_bind.go -------
type BodyAParam struct {
 Name string `json:"name"`
}
type BodyBParam struct {
 Home string `json:"home"`
}
// 重複綁定request.Body(錯誤示例)
func TestBindBody(engine *gin.Engine) {
 engine.POST("/body", func(context *gin.Context) {
  paramA := BodyAParam{}
  paramB := BodyBParam{}
  // c.ShouldBind 使用了 c.Request.Body,不可重用。
  _ = context.ShouldBindJSON(mA)
  // 因爲現在 c.Request.Body 是 EOF,所以這裏會報錯。
  _ = context.ShouldBindJSON(mB)
  context.JSON(200,gin.H{"paramA":paramA,"paramB":paramB})
 })
}

b. 請求返回

# 發現只有paramA綁定成功
➜ curl -X POST http://127.0.0.1:8080/body -d '{"name":"李四","home":"上海"}'
{"paramA":{"name":"李四"},"paramB":{"home":""}}

5.2 正確示例

a. 代碼

//-------- main.go ---------------
package main
import (
 "github.com/gin-gonic/gin" // 引入Gin框架
 "go-use/practise" // 代碼示例包
)
func main() {
 engine := gin.Default()
 practise.TestBindXml(engine)
 _ = engine.Run()
}
//------ go-use/practise/param_bind.go -------
type BodyAParam struct {
 Name string `json:"name"`
}
type BodyBParam struct {
 Home string `json:"home"`
}
// 重複綁定request.Body(正確示例)
func TestBindBody2(engine *gin.Engine) {
 engine.POST("/body2", func(context *gin.Context) {
  paramA := BodyAParam{}
  paramB := BodyBParam{}
  // 讀取 c.Request.Body 並將結果存入上下文。
  _ = context.ShouldBindBodyWith(mA,binding.JSON)
  // 這時, 複用存儲在上下文中的 body。
  _ = context.ShouldBindBodyWith(mB,binding.JSON)
  context.JSON(200,gin.H{"paramA":paramA,"paramB":paramB})
 })
}

b. 請求返回

# paramA和paramB都綁定成功
➜ curl -X POST http://127.0.0.1:8080/body2 -d '{"name":"李四","home":"上海"}'
{"paramA":{"name":"李四"},"paramB":{"home":"上海"}}
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/DKSsCtcORSpAKb18aHnAYw