日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 人文社科 > 生活经验 >内容正文

生活经验

Gin 框架学习笔记(02)— 参数自动绑定到结构体

發(fā)布時(shí)間:2023/11/28 生活经验 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Gin 框架学习笔记(02)— 参数自动绑定到结构体 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

參數(shù)綁定模型可以將請(qǐng)求體自動(dòng)綁定到結(jié)構(gòu)體中,目前支持綁定的請(qǐng)求類型有 JSONXMLYAML 和標(biāo)準(zhǔn)表單 form數(shù)據(jù) foo=bar&boo=baz 等。換句話說(shuō),只要定義好結(jié)構(gòu)體,就可以將請(qǐng)求中包含的數(shù)據(jù)自動(dòng)接收過(guò)來(lái),這是 Gin 框架非常神奇的功能。
?

在定義綁定對(duì)應(yīng)的結(jié)構(gòu)體時(shí),需要給結(jié)構(gòu)體字段設(shè)置綁定類型的標(biāo)簽,比如綁定 JSON 數(shù)據(jù)時(shí),設(shè)置字段標(biāo)簽為 json:"fieldname" 。使用綁定可以更快捷地把數(shù)據(jù)傳遞給程序中的數(shù)據(jù)對(duì)象。
?

使用 Gin框架中系列綁定有關(guān)方法時(shí),Gin 會(huì)根據(jù)請(qǐng)求頭中 Content-Type 推斷如何綁定,也就是自動(dòng)綁定。但如果明確綁定的類型,開(kāi)發(fā)人員也可以使用 MustBindWith() 方法或 BindJSON() 等方法而不用自動(dòng)推斷。可以指定結(jié)構(gòu)體某字段是必需的,字段需要設(shè)置標(biāo)簽 binding:"required" ,但如果綁定時(shí)是空值,Gin 會(huì)報(bào)錯(cuò)。
?

Gin 框架的 binding 包中,定義了 Content-Type 請(qǐng)求頭信息的多種 MIME 類型,以便在自動(dòng)綁定時(shí)進(jìn)行類型判別進(jìn)而采用對(duì)應(yīng)的處理方法:

const (MIMEJSON              = "application/json"MIMEHTML              = "text/html"MIMEXML               = "application/xml"MIMEXML2              = "text/xml"MIMEPlain             = "text/plain"MIMEPOSTForm          = "application/x-www-form-urlencoded"MIMEMultipartPOSTForm = "multipart/form-data"MIMEPROTOBUF          = "application/x-protobuf"MIMEMSGPACK           = "application/x-msgpack"MIMEMSGPACK2          = "application/msgpack"MIMEYAML              = "application/x-yaml"
)

在所有綁定的方法中,首先 c.Bind() 方法會(huì)根據(jù) Content-Type 推斷得到一個(gè) bindding 實(shí)例對(duì)象。因?yàn)樗鼤?huì)調(diào)用函數(shù) func Default(method, contentType string) Binding ,這個(gè)函數(shù)根據(jù) HTTP 請(qǐng)求的方法和 Content-Type 來(lái)實(shí)例化具體的 bindding 對(duì)象。一共可以實(shí)例化為下面幾種類型:

var (JSON          = jsonBinding{}XML           = xmlBinding{}Form          = formBinding{}Query         = queryBinding{}FormPost      = formPostBinding{}FormMultipart = formMultipartBinding{}ProtoBuf      = protobufBinding{}MsgPack       = msgpackBinding{}YAML          = yamlBinding{}Uri           = uriBinding{}Header        = headerBinding{}
)

binding 包也就是 binding 目錄中,可以看到每種實(shí)例結(jié)構(gòu)都單獨(dú)在一個(gè)文件定義了系列處理方法。 c.Bind() 方法得到 binding 實(shí)例對(duì)象后,會(huì)調(diào)用 c.MustBindWith(obj, b) 方法, b 為實(shí)例化的某類 binding 對(duì)象,而像 c.BindJSON() 方法由于知道實(shí)例化對(duì)象是 JSON ,所以也調(diào)用 c.MustBindWith(obj, b) ,這里的 bjsonBinding{} 對(duì)象。其他像 XML 等的處理過(guò)程類似。
?

c.MustBindWith() 方法會(huì)統(tǒng)一調(diào)用 c.ShouldBindWith() 方法,在 c.ShouldBindWith() 方法中會(huì)調(diào)用具體實(shí)例的處理方法: b.Bind(c.Request, obj) ,這個(gè) b.Bind()方法很關(guān)鍵,每種 binding 實(shí)例對(duì)象都有實(shí)現(xiàn)這個(gè)方法,它實(shí)現(xiàn)了參數(shù)的綁定功能。
?

在參數(shù)綁定過(guò)程中,大致可以認(rèn)為是這個(gè)過(guò)程:

Bind->MustBindWith->ShouldBindWith->b.Bind

在參數(shù)綁定中,無(wú)論是采用 c.Bind() 系列方法、或者是 c.ShouldBindWith() 系列方法,最終都是通過(guò)具體實(shí)例的 b.Bind() 方法來(lái)實(shí)現(xiàn)參數(shù)綁定到結(jié)構(gòu)體指針。而這個(gè)實(shí)例可以在 binding 目錄中找到其方法的實(shí)現(xiàn)文件。如: json.gouri.go 以及 form.go 等等文件,文件名都對(duì)應(yīng)著不同的 Content-Type
?

Gin 框架中下列方法可以用處理綁定:

// Bind 檢查 Content-Type 來(lái)自動(dòng)選擇綁定引擎
// 依靠 "Content-Type" 頭來(lái)使用不同的綁定
//     "application/json" 綁定 JSON
//     "application/xml"  綁定 XML
// 否則返回錯(cuò)誤信息
// 如果 Content-Type ==“application / json”,JSON 或 XML 作為 JSON 輸入,
// Bind 會(huì)將請(qǐng)求的主體解析為 JSON。
// 它將 JSON 有效負(fù)載解碼為指定為指針的結(jié)構(gòu)。
// 如果輸入無(wú)效,它會(huì)寫入 400 錯(cuò)誤并在響應(yīng)中設(shè)置 Content-Type 標(biāo)題 “text / plain” 。
func (c *Context) Bind(obj interface{}) error// BindJSON 是 c.MustBindWith(obj, binding.JSON) 的簡(jiǎn)寫
func (c *Context) BindJSON(obj interface{}) error// BindXML 是 c.MustBindWith(obj, binding.BindXML) 的簡(jiǎn)寫
func (c *Context) BindXML(obj interface{}) error// BindQuery 是 c.MustBindWith(obj, binding.Query) 的簡(jiǎn)寫
func (c *Context) BindQuery(obj interface{}) error// BindYAML 是 c.MustBindWith(obj, binding.YAML) 的簡(jiǎn)寫
func (c *Context) BindYAML(obj interface{}) error// BindHeader 是 c.MustBindWith(obj, binding.Header) 的簡(jiǎn)寫
func (c *Context) BindHeader(obj interface{}) error// BindUri 使用 binding.Uri 綁定傳遞的結(jié)構(gòu)體指針。
// 如果發(fā)生任何錯(cuò)誤,它將使用 HTTP 400 中止請(qǐng)求。
func (c *Context) BindUri(obj interface{}) error// MustBindWith 使用指定的綁定引擎綁定傳遞的 struct 指針。
// 如果發(fā)生任何錯(cuò)誤,它將使用 HTTP 400 中止請(qǐng)求。
func (c *Context) MustBindWith(obj interface{}, b binding.Binding) error// ShouldBind 檢查 Content-Type 來(lái)自動(dòng)選擇綁定引擎
// 依靠 "Content-Type" 頭來(lái)使用不同的綁定
//     "application/json" 綁定 JSON
//     "application/xml"  綁定 XML
// 否則返回錯(cuò)誤信息
// 如果 Content-Type ==“application/json” ,JSON 或 XML 作為 JSON 輸入,
// Bind 會(huì)將請(qǐng)求的主體解析為JSON。
// 它將 JSON 有效負(fù)載解碼為指定為指針的結(jié)構(gòu)。
// 類似 c.Bind() ,但這個(gè)方法在 JSON 無(wú)效時(shí)不支持寫 400 到響應(yīng)里。
func (c *Context) ShouldBind(obj interface{}) error// ShouldBindJSON  是c.ShouldBindWith(obj, binding.JSON)的簡(jiǎn)寫
func (c *Context) ShouldBindJSON(obj interface{}) error// ShouldBindXML  是c.ShouldBindWith(obj, binding.XML)的簡(jiǎn)寫
func (c *Context) ShouldBindXML(obj interface{}) error// ShouldBindQuery  是c.ShouldBindWith(obj, binding.Query)的簡(jiǎn)寫
func (c *Context) ShouldBindQuery(obj interface{}) error// ShouldBindYAML  是c.ShouldBindWith(obj, binding.YAML)的簡(jiǎn)寫
func (c *Context) ShouldBindYAML(obj interface{}) error// ShouldBindHeader  是c.ShouldBindWith(obj, binding.Header)的簡(jiǎn)寫
func (c *Context) ShouldBindHeader(obj interface{}) error// ShouldBindUri使用指定的綁定引擎綁定傳遞的struct指針。
func (c *Context) ShouldBindUri(obj interface{}) error// ShouldBindWith使用自定的綁定引擎綁定傳遞的struct指針。
func (c *Context) ShouldBindWith(obj interface{}, b binding.Binding) error// ShouldBindBodyWith與ShouldBindWith類似,但它存儲(chǔ)請(qǐng)求
// ShouldBindBodyWith可進(jìn)入上下文,并在再次調(diào)用時(shí)重用。
//
// 注意:此方法在綁定之前讀取正文。 所以推薦使用
// 如果只需要調(diào)用一次,那么ShouldBindWith可以獲得更好的性能。
func (c *Context) ShouldBindBodyWith(obj interface{}, bb binding.BindingBody) (err error)

1. 綁定查詢字符串或表單數(shù)據(jù)

表單和 URLQuery 方式傳遞參數(shù),程序通過(guò)綁定的方式得到參數(shù)值,在參數(shù)的提取上更加自動(dòng)。

package mainimport ("log""github.com/gin-gonic/gin"
)type Person struct {Name     string    `form:"name"`Address  string    `form:"address"`
}func main() {route := gin.Default()route.POST("/testing", startPage)route.Run(":8080")
}func startPage(c *gin.Context) {var person Person// 如果是 `GET` 請(qǐng)求,只使用 `Form` 綁定引擎(`query`)。// 如果是 `POST` 請(qǐng)求,首先檢查 `content-type` 是否為 `JSON` 或 `XML`,// 然后再使用 `Form`(`form-data`)。if c.ShouldBind(&person) == nil {log.Println(person.Name)log.Println(person.Address)}c.String(200, "Success")
}

程序運(yùn)行在 Debug 模式時(shí),在命令行運(yùn)行下面三條命令:

curl -X POST  "http://localhost:8080/testing?name=appleboy&address=xyz"curl -H "Content-Type:application/json"  -X POST -d '{"name":"appleeboy","address":"xyz"}' <http://localhost:8080/testing>curl -H "Content-Type:application/x-www-form-urlencoded" -X POST -d "name=appleboy&address=xyz" "<http://localhost:8080/testing>"

輸出結(jié)果:

[GIN-debug] Listening and serving HTTP on :8080
2019/07/13 12:54:34 appleboy
2019/07/13 12:54:34 xyz
[GIN] 2019/07/13 - 12:54:34 | 200 | 18.9504ms | 127.0.0.1 | POST /testing?name=appleboy&address=xyz
2019/07/13 12:54:38 appleeboy
2019/07/13 12:54:38 xyz
[GIN] 2019/07/13 - 12:54:38 | 200 | 0s | 127.0.0.1 | POST /testing
2019/07/13 12:54:46 appleboy
2019/07/13 12:54:46 xyz
[GIN] 2019/07/13 - 12:54:46 | 200 | 0s | 127.0.0.1 | POST /testing

通過(guò) POST 方法,采用 Urlencoded 編碼或 JSON 方式都能被綁定正常解析。但如果把程序接收方法改為 GET 方法:

route.GET("/testing", startPage)

則只能通過(guò) URL Query 傳遞參數(shù):

curl -X GET "http://localhost:8080/testing?name=appleboy&address=xyz"

這樣通過(guò) URL Query 傳遞參數(shù)也能被正常綁定。
?

2. Multipart/Urlencoded 綁定

通過(guò)表單傳遞參數(shù),下面程序通過(guò)綁定的方式得到參數(shù)值。

type LoginForm struct {User     string `form:"user" binding:"required"`Password string `form:"password" binding:"required"`
}func main() {router := gin.Default()router.POST("/login", func(c *gin.Context) {var form LoginForm// 可顯式綁定表單// c.ShouldBindWith(&form, binding.Form)// 或者簡(jiǎn)單地使用 ShouldBind 方法自動(dòng)綁定if c.ShouldBind(&form) == nil {if form.User == "user" && form.Password == "password" {c.JSON(200, gin.H{"status": "you are logged in"})} else {c.JSON(401, gin.H{"status": "unauthorized"})}}})router.Run(":8080")
}

上面程序中結(jié)構(gòu)體的標(biāo)簽: form:"user" ,表示在 form 表單中的名為 user

User     string `form:"user" binding:"required"`
Password string `form:"password" binding:"required"`

程序運(yùn)行在 Debug 模式時(shí),在命令行運(yùn)行下面兩條命令:

curl -X POST  -d "user=user&password=password" <http://localhost:8080/login>Curl -H "Content-Type:multipart/form-data" -X POST -d "user=user&password=password" http://localhost:8080/login

3. URI 參數(shù)綁定

Gin 框架支持在路由 URI 中存在參數(shù),也支持通過(guò)綁定得到這些參數(shù),需要在結(jié)構(gòu)體中指定字段標(biāo)簽為 uri

package mainimport "github.com/gin-gonic/gin"type Person struct {ID string `uri:"id" binding:"required,uuid"`Name string `uri:"name" binding:"required"`
}func main() {route := gin.Default()route.GET("/:name/:id", func(c *gin.Context) {var person Personif err := c.ShouldBindUri(&person); err != nil {c.JSON(400, gin.H{"msg": err})return}c.JSON(200, gin.H{"name": person.Name, "uuid": person.ID})})route.Run(":8088")
}

上面程序中結(jié)構(gòu)體的標(biāo)簽: uri:"id" ,表示在 URI 中的參數(shù)名為 id

UserID  string `uri:"id" binding:"required"`
Name   string `uri:"name" binding:"required"`

程序運(yùn)行在 Debug 模式時(shí),在命令行運(yùn)行下面命令:

curl  -X GET http://localhost:8080/Go/42

4. 綁定 HTML 復(fù)選框

Gin 框架很方便地通過(guò)綁定得到 HTML FORM 元素的值,需要在結(jié)構(gòu)體中指定字段標(biāo)簽form:filedname

type CheckForm struct {Colors []string `form:"colors[]"`
}func main() {router := gin.Default()router.Static("/", "./public")router.POST("/check", func(c *gin.Context) {var form CheckForm// 簡(jiǎn)單地使用 ShouldBind 方法自動(dòng)綁定if c.ShouldBind(&form) == nil {c.JSON(200, gin.H{"color": form.Colors})}})router.Run(":8080")
}

index.html 文件放在程序目錄下 public 目錄中。

<form action="/check" method="POST"><p>Check some colors</p><label for="red">Red</label><input type="checkbox" name="colors[]" value="red" id="red"><label for="green">Green</label><input type="checkbox" name="colors[]" value="green" id="green"><label for="blue">Blue</label><input type="checkbox" name="colors[]" value="blue" id="blue"><input type="submit">
</form>

注意,上面程序中結(jié)構(gòu)體標(biāo)簽: colors[] 與復(fù)選框的名字一致,這里表示數(shù)組所以可以得到多個(gè)已選項(xiàng)的值。
運(yùn)行程序,通過(guò)瀏覽器訪問(wèn) http://localhost:8080/ ,出現(xiàn)復(fù)選框表單,選擇兩個(gè)以上選項(xiàng),這里選擇紅,綠兩種顏色,然后提交表單(請(qǐng)求發(fā)送到 http://localhost:8080/check )。
?

頁(yè)面顯示,符合提交的選項(xiàng):

{"color":["red","green"]}

5. 綁定表單數(shù)據(jù)至嵌入結(jié)構(gòu)體

前面已經(jīng)知道通過(guò)綁定可以自動(dòng)取得數(shù)據(jù)到簡(jiǎn)單結(jié)構(gòu)體對(duì)象,對(duì)有嵌入的結(jié)構(gòu)體也可以通過(guò)綁定自動(dòng)得到數(shù)據(jù),不過(guò)嵌入的結(jié)構(gòu)體后面不要指定標(biāo)簽。

type StructA struct {FieldA string `form:"field_a"`
}type StructB struct {NestedStruct StructA // 不要指定標(biāo)簽FieldB string `form:"field_b"`
}type StructC struct {NestedStructPointer *StructAFieldC string `form:"field_c"`
}type StructD struct {NestedAnonyStruct struct {FieldX string `form:"field_x"`}FieldD string `form:"field_d"`
}func GetDataB(c *gin.Context) {var b StructBc.Bind(&b)c.JSON(200, gin.H{"a": b.NestedStruct,"b": b.FieldB,})
}func GetDataC(c *gin.Context) {var b StructCc.Bind(&b)c.JSON(200, gin.H{"a": b.NestedStructPointer,"c": b.FieldC,})
}func GetDataD(c *gin.Context) {var b StructDc.Bind(&b)c.JSON(200, gin.H{"x": b.NestedAnonyStruct,"d": b.FieldD,})
}func main() {router := gin.Default()router.GET("/getb", GetDataB)router.GET("/getc", GetDataC)router.GET("/getd", GetDataD)router.Run()
}

輸入輸出結(jié)果:

curl "http://localhost:8080/getb?field_a=hello&field_b=world"
Go{"a":{"FieldA":"hello"},"b":"world"}curl "http://localhost:8080/getc?field_a=hello&field_c=world"
Go{"a":{"FieldA":"hello"},"c":"world"}curl "http://localhost:8080/getd?field_x=hello&field_d=world"
Go{"d":"world","x":{"FieldX":"hello"}}

6. 將請(qǐng)求體綁定到不同的結(jié)構(gòu)體中

一般通過(guò)調(diào)用 ShouldBind() 方法綁定數(shù)據(jù),但注意某些情況不能多次調(diào)用這個(gè)方法。

type formA struct {Foo string `json:"foo" xml:"foo" binding:"required"`
}type formB struct {Bar string `json:"bar" xml:"bar" binding:"required"`
}func BindHandler(c *gin.Context) {objA := formA{}objB := formB{}// c.ShouldBind 使用了 c.Request.Body ,不可重用。if errA := c.ShouldBind(&objA); errA != nil {fmt.Println(errA)c.String(http.StatusOK, `the body should be formA`)// 因?yàn)楝F(xiàn)在 c.Request.Body 是 EOF,所以這里會(huì)報(bào)錯(cuò)。} else if errB := c.ShouldBind(&objB); errB != nil {fmt.Println(errB)c.String(http.StatusOK, `the body should be formB`)} else {c.String(http.StatusOK, `Success`)}
}func main() {route := gin.Default()route.Any("/bind", BindHandler)route.Run(":8080")
}

運(yùn)行程序,通過(guò)瀏覽器訪問(wèn) http://localhost:8080/bind?foo=foo&bar=bar ,頁(yè)面顯示:
the body should be formA
程序運(yùn)行在 Debug 模式時(shí),在命令行運(yùn)行下面命令:

curl -H "Content-Type:application/json" -v -X POST  -d '{"foo":"foo","bar":"bar"}'  http://localhost:8080/bind

命令返回:
the body should be formB
表明在第二次運(yùn)行 ShouldBind() 方法時(shí)出錯(cuò),要想多次綁定,可以使用 c.ShouldBindBodyWith() 方法。

func BindHandler(c *gin.Context) {objA := formA{}objB := formB{}// ShouldBindBodyWith() 讀取 c.Request.Body 并將結(jié)果存入上下文。if errA := c.ShouldBindBodyWith(&objA, binding.JSON); errA != nil {fmt.Println(errA)c.String(http.StatusOK, `the body should be formA`)// 這時(shí), 復(fù)用存儲(chǔ)在上下文中的 body 。} else if errB := c.ShouldBindBodyWith(&objB, binding.JSON); errB != nil {fmt.Println(errB)c.String(http.StatusOK, `the body should be formB JSON`)// 可以接受其他格式} else {c.String(http.StatusOK, `Success`)}
}

c.ShouldBindBodyWith() 會(huì)在綁定之前將請(qǐng)求體存儲(chǔ)到上下文中。 這會(huì)對(duì)性能造成輕微影響,如果調(diào)用一次就能完成綁定的話,那就不要用這個(gè)方法。
只有某些格式需要此功能,如 JSONXMLMsgPackProtoBuf 。對(duì)于其他格式,如 QueryFormFormPostFormMultipart 可以多次調(diào)用 c.ShouldBind() 而不會(huì)造成任任何性能損失,這也是前面結(jié)構(gòu)體中的標(biāo)簽沒(méi)有定義 form ,只有定義 json:"foo" xml:"foo" binding:"required" 的原因。

7. 只綁定 URL Query 參數(shù)

ShouldBind() 方法支持 URL Query 參數(shù)綁定,也支持 POST 參數(shù)綁定。而 ShouldBindQuery() 方法只綁定 URL Query 參數(shù)而忽略 POST 數(shù)據(jù)。

type Person struct {Name    string `form:"name"`Address string `form:"address"`
}func startPage(c *gin.Context) {var person Personif c.ShouldBindQuery(&person) == nil {fmt.Println(person.Name)fmt.Println(person.Address)c.String(200, "Success")} else {c.String(400, "Error")}}func main() {route := gin.Default()route.Any("/bindquery", startPage)route.Run(":8080")
}

運(yùn)行程序,通過(guò)瀏覽器訪問(wèn) http://localhost:8080/ ,頁(yè)面顯示 “Sucess” 。輸出結(jié)果:

[GIN-debug] GET /bindquery --> main.startPage (3 handlers)
[GIN-debug] POST /bindquery --> main.startPage (3 handlers)
[GIN-debug] PUT /bindquery --> main.startPage (3 handlers)
[GIN-debug] PATCH /bindquery --> main.startPage (3 handlers)
[GIN-debug] HEAD /bindquery --> main.startPage (3 handlers)
[GIN-debug] OPTIONS /bindquery --> main.startPage (3 handlers)
[GIN-debug] DELETE /bindquery --> main.startPage (3 handlers)
[GIN-debug] CONNECT /bindquery --> main.startPage (3 handlers)
[GIN-debug] TRACE /bindquery --> main.startPage (3 handlers)
[GIN-debug] Listening and serving HTTP on :8080
titan
cs
[GIN] 2019/07/13 - 17:06:23 | 200 | 0s | ::1 | GET /bindquery?name=titan&address=cs

輸出表明 URL Query 參數(shù)通過(guò) GET 方法能被程序正常綁定,注意上面程序中使用了 Any() 方法,它能匹配眾多的 HTTP 方法。
如果程序繼續(xù)運(yùn)行在 Debug 模式時(shí),在命令行運(yùn)行下面命令:

curl -v -X POST  -d "name=titan&address=cs"  http://localhost:8080/bindquery* Connected to localhost (::1) port 8080 (#0)
> POST /bindquery HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.55.1
> Accept: */*
> Content-Length: 21
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 21 out of 21 bytes
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=utf-8
< Date: Sat, 13 Jul 2019 17:12:37
< Content-Length: 7
<
Success

命令行的返回表明通過(guò) POST 方法已經(jīng)成功提交請(qǐng)求,服務(wù)端成功返回,狀態(tài)代碼: 200 ,返回內(nèi)容: Success 。
控制臺(tái)輸出結(jié)果:

[GIN] 2019/07/13 - 17:12:37 | 200 | 0s | ::1 | POST /bindquery

從控制臺(tái)輸出可以看到,通過(guò) POST 提交的數(shù)據(jù)沒(méi)有正常綁定。但是前面通過(guò) ShouldBind() 方法可以正常綁定。這表明 ShouldBindQuery() 只綁定 URL Query 參數(shù)而忽略 POST 數(shù)據(jù)。

8. JSON 模型綁定

通過(guò) POST 方法提交 JSON 格式數(shù)據(jù),程序通過(guò)綁定的方式得到 JSON 數(shù)據(jù),并傳遞給結(jié)構(gòu)體,但需要指定字段標(biāo)簽為 json

// 綁定 JSON
type Login struct {User     string `form:"user" json:"user" xml:"user"  binding:"required"`Password string `form:"password" json:"password" xml:"password" binding:"required"`
}func main() {router := gin.Default()// 綁定 JSON ({"user": "manu", "password": "123"})router.POST("/loginJSON", func(c *gin.Context) {var json Loginif err := c.ShouldBindJSON(&json); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}if json.User != "manu" || json.Password != "123" {c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})return}c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})})// 綁定 HTML 表單 (user=manu&password=123)router.POST("/loginForm", func(c *gin.Context) {var form Login// 根據(jù) Content-Type Header 推斷使用哪個(gè)綁定器。if err := c.ShouldBind(&form); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}if form.User != "manu" || form.Password != "123" {c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})return}c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})})// 監(jiān)聽(tīng)并啟動(dòng)服務(wù)router.Run(":8080")
}

輸出結(jié)果:

curl -v  -H 'content-type: application/json' -X POST  http://localhost:8080/loginJSON   -d '{ "user": "manu" , "password" :"123" }'> POST /loginJSON HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.47.0
> Accept: */*
> content-type: application/json
> Content-Length: 38
>
* upload completely sent off: 38 out of 38 bytes
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Date: Sat, 13 Jul 2019 15:08:29 GMT
< Content-Length: 31
<
{"status":"you are logged in"}

9. Header 頭信息綁定

Header 也可以傳遞參數(shù),程序通過(guò)綁定的方式得到參數(shù)值,在結(jié)構(gòu)體的字段標(biāo)簽上需要指定為 header

type testHeader struct {Rate   int    `header:"Rate"`Domain string `header:"Domain"`
}func main() {router := gin.Default()router.GET("/", func(c *gin.Context) {h := testHeader{}if err := c.ShouldBindHeader(&h); err != nil {c.JSON(200, err)}fmt.Printf("%#v\\n", h)c.JSON(200, gin.H{"Rate": h.Rate, "Domain": h.Domain})})router.Run(":8080")
}

運(yùn)行命令

curl -H "rate:300" -H "domain:music" http://localhost:8080/{"Domain":"music","Rate":300}

通過(guò) curl 命令帶上自定義的頭部信息給 Handler 處理程序, ShouldBindHeader() 方法自動(dòng)綁定頭部變量到結(jié)構(gòu)體。
?

參考:https://gitbook.cn/gitchat/column/5dab061e7d66831b22aa0b44/topic/5dab09f37d66831b22aa0b5d

總結(jié)

以上是生活随笔為你收集整理的Gin 框架学习笔记(02)— 参数自动绑定到结构体的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。