Gin 框架学习笔记(02)— 参数自动绑定到结构体
參數(shù)綁定模型可以將請求體自動綁定到結(jié)構(gòu)體中,目前支持綁定的請求類型有 JSON 、XML 、YAML 和標(biāo)準(zhǔn)表單 form數(shù)據(jù) foo=bar&boo=baz 等。換句話說,只要定義好結(jié)構(gòu)體,就可以將請求中包含的數(shù)據(jù)自動接收過來,這是 Gin 框架非常神奇的功能。
?
在定義綁定對應(yīng)的結(jié)構(gòu)體時,需要給結(jié)構(gòu)體字段設(shè)置綁定類型的標(biāo)簽,比如綁定 JSON 數(shù)據(jù)時,設(shè)置字段標(biāo)簽為 json:"fieldname" 。使用綁定可以更快捷地把數(shù)據(jù)傳遞給程序中的數(shù)據(jù)對象。
?
使用 Gin框架中系列綁定有關(guān)方法時,Gin 會根據(jù)請求頭中 Content-Type 推斷如何綁定,也就是自動綁定。但如果明確綁定的類型,開發(fā)人員也可以使用 MustBindWith() 方法或 BindJSON() 等方法而不用自動推斷。可以指定結(jié)構(gòu)體某字段是必需的,字段需要設(shè)置標(biāo)簽 binding:"required" ,但如果綁定時是空值,Gin 會報錯。
?
在 Gin 框架的 binding 包中,定義了 Content-Type 請求頭信息的多種 MIME 類型,以便在自動綁定時進行類型判別進而采用對應(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() 方法會根據(jù) Content-Type 推斷得到一個 bindding 實例對象。因為它會調(diào)用函數(shù) func Default(method, contentType string) Binding ,這個函數(shù)根據(jù) HTTP 請求的方法和 Content-Type 來實例化具體的 bindding 對象。一共可以實例化為下面幾種類型:
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 目錄中,可以看到每種實例結(jié)構(gòu)都單獨在一個文件定義了系列處理方法。 c.Bind() 方法得到 binding 實例對象后,會調(diào)用 c.MustBindWith(obj, b) 方法, b 為實例化的某類 binding 對象,而像 c.BindJSON() 方法由于知道實例化對象是 JSON ,所以也調(diào)用 c.MustBindWith(obj, b) ,這里的 b 是 jsonBinding{} 對象。其他像 XML 等的處理過程類似。
?
而 c.MustBindWith() 方法會統(tǒng)一調(diào)用 c.ShouldBindWith() 方法,在 c.ShouldBindWith() 方法中會調(diào)用具體實例的處理方法: b.Bind(c.Request, obj) ,這個 b.Bind()方法很關(guān)鍵,每種 binding 實例對象都有實現(xiàn)這個方法,它實現(xiàn)了參數(shù)的綁定功能。
?
在參數(shù)綁定過程中,大致可以認(rèn)為是這個過程:
Bind->MustBindWith->ShouldBindWith->b.Bind
在參數(shù)綁定中,無論是采用 c.Bind() 系列方法、或者是 c.ShouldBindWith() 系列方法,最終都是通過具體實例的 b.Bind() 方法來實現(xiàn)參數(shù)綁定到結(jié)構(gòu)體指針。而這個實例可以在 binding 目錄中找到其方法的實現(xiàn)文件。如: json.go 、 uri.go 以及 form.go 等等文件,文件名都對應(yīng)著不同的 Content-Type 。
?
在 Gin 框架中下列方法可以用處理綁定:
// Bind 檢查 Content-Type 來自動選擇綁定引擎
// 依靠 "Content-Type" 頭來使用不同的綁定
// "application/json" 綁定 JSON
// "application/xml" 綁定 XML
// 否則返回錯誤信息
// 如果 Content-Type ==“application / json”,JSON 或 XML 作為 JSON 輸入,
// Bind 會將請求的主體解析為 JSON。
// 它將 JSON 有效負(fù)載解碼為指定為指針的結(jié)構(gòu)。
// 如果輸入無效,它會寫入 400 錯誤并在響應(yīng)中設(shè)置 Content-Type 標(biāo)題 “text / plain” 。
func (c *Context) Bind(obj interface{}) error// BindJSON 是 c.MustBindWith(obj, binding.JSON) 的簡寫
func (c *Context) BindJSON(obj interface{}) error// BindXML 是 c.MustBindWith(obj, binding.BindXML) 的簡寫
func (c *Context) BindXML(obj interface{}) error// BindQuery 是 c.MustBindWith(obj, binding.Query) 的簡寫
func (c *Context) BindQuery(obj interface{}) error// BindYAML 是 c.MustBindWith(obj, binding.YAML) 的簡寫
func (c *Context) BindYAML(obj interface{}) error// BindHeader 是 c.MustBindWith(obj, binding.Header) 的簡寫
func (c *Context) BindHeader(obj interface{}) error// BindUri 使用 binding.Uri 綁定傳遞的結(jié)構(gòu)體指針。
// 如果發(fā)生任何錯誤,它將使用 HTTP 400 中止請求。
func (c *Context) BindUri(obj interface{}) error// MustBindWith 使用指定的綁定引擎綁定傳遞的 struct 指針。
// 如果發(fā)生任何錯誤,它將使用 HTTP 400 中止請求。
func (c *Context) MustBindWith(obj interface{}, b binding.Binding) error// ShouldBind 檢查 Content-Type 來自動選擇綁定引擎
// 依靠 "Content-Type" 頭來使用不同的綁定
// "application/json" 綁定 JSON
// "application/xml" 綁定 XML
// 否則返回錯誤信息
// 如果 Content-Type ==“application/json” ,JSON 或 XML 作為 JSON 輸入,
// Bind 會將請求的主體解析為JSON。
// 它將 JSON 有效負(fù)載解碼為指定為指針的結(jié)構(gòu)。
// 類似 c.Bind() ,但這個方法在 JSON 無效時不支持寫 400 到響應(yīng)里。
func (c *Context) ShouldBind(obj interface{}) error// ShouldBindJSON 是c.ShouldBindWith(obj, binding.JSON)的簡寫
func (c *Context) ShouldBindJSON(obj interface{}) error// ShouldBindXML 是c.ShouldBindWith(obj, binding.XML)的簡寫
func (c *Context) ShouldBindXML(obj interface{}) error// ShouldBindQuery 是c.ShouldBindWith(obj, binding.Query)的簡寫
func (c *Context) ShouldBindQuery(obj interface{}) error// ShouldBindYAML 是c.ShouldBindWith(obj, binding.YAML)的簡寫
func (c *Context) ShouldBindYAML(obj interface{}) error// ShouldBindHeader 是c.ShouldBindWith(obj, binding.Header)的簡寫
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類似,但它存儲請求
// ShouldBindBodyWith可進入上下文,并在再次調(diào)用時重用。
//
// 注意:此方法在綁定之前讀取正文。 所以推薦使用
// 如果只需要調(diào)用一次,那么ShouldBindWith可以獲得更好的性能。
func (c *Context) ShouldBindBodyWith(obj interface{}, bb binding.BindingBody) (err error)
1. 綁定查詢字符串或表單數(shù)據(jù)
表單和 URLQuery 方式傳遞參數(shù),程序通過綁定的方式得到參數(shù)值,在參數(shù)的提取上更加自動。
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` 請求,只使用 `Form` 綁定引擎(`query`)。// 如果是 `POST` 請求,首先檢查 `content-type` 是否為 `JSON` 或 `XML`,// 然后再使用 `Form`(`form-data`)。if c.ShouldBind(&person) == nil {log.Println(person.Name)log.Println(person.Address)}c.String(200, "Success")
}
程序運行在 Debug 模式時,在命令行運行下面三條命令:
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
通過 POST 方法,采用 Urlencoded 編碼或 JSON 方式都能被綁定正常解析。但如果把程序接收方法改為 GET 方法:
route.GET("/testing", startPage)
則只能通過 URL Query 傳遞參數(shù):
curl -X GET "http://localhost:8080/testing?name=appleboy&address=xyz"
這樣通過 URL Query 傳遞參數(shù)也能被正常綁定。
?
2. Multipart/Urlencoded 綁定
通過表單傳遞參數(shù),下面程序通過綁定的方式得到參數(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)// 或者簡單地使用 ShouldBind 方法自動綁定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"`
程序運行在 Debug 模式時,在命令行運行下面兩條命令:
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ù),也支持通過綁定得到這些參數(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"`
程序運行在 Debug 模式時,在命令行運行下面命令:
curl -X GET http://localhost:8080/Go/42
4. 綁定 HTML 復(fù)選框
Gin 框架很方便地通過綁定得到 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// 簡單地使用 ShouldBind 方法自動綁定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ù)組所以可以得到多個已選項的值。
運行程序,通過瀏覽器訪問 http://localhost:8080/ ,出現(xiàn)復(fù)選框表單,選擇兩個以上選項,這里選擇紅,綠兩種顏色,然后提交表單(請求發(fā)送到 http://localhost:8080/check )。
?
頁面顯示,符合提交的選項:
{"color":["red","green"]}
5. 綁定表單數(shù)據(jù)至嵌入結(jié)構(gòu)體
前面已經(jīng)知道通過綁定可以自動取得數(shù)據(jù)到簡單結(jié)構(gòu)體對象,對有嵌入的結(jié)構(gòu)體也可以通過綁定自動得到數(shù)據(jù),不過嵌入的結(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. 將請求體綁定到不同的結(jié)構(gòu)體中
一般通過調(diào)用 ShouldBind() 方法綁定數(shù)據(jù),但注意某些情況不能多次調(diào)用這個方法。
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`)// 因為現(xiàn)在 c.Request.Body 是 EOF,所以這里會報錯。} 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")
}
運行程序,通過瀏覽器訪問 http://localhost:8080/bind?foo=foo&bar=bar ,頁面顯示:
the body should be formA
程序運行在 Debug 模式時,在命令行運行下面命令:
curl -H "Content-Type:application/json" -v -X POST -d '{"foo":"foo","bar":"bar"}' http://localhost:8080/bind
命令返回:
the body should be formB
表明在第二次運行 ShouldBind() 方法時出錯,要想多次綁定,可以使用 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`)// 這時, 復(fù)用存儲在上下文中的 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() 會在綁定之前將請求體存儲到上下文中。 這會對性能造成輕微影響,如果調(diào)用一次就能完成綁定的話,那就不要用這個方法。
只有某些格式需要此功能,如 JSON ,XML ,MsgPack ,ProtoBuf 。對于其他格式,如 Query ,Form ,FormPost ,FormMultipart 可以多次調(diào)用 c.ShouldBind() 而不會造成任任何性能損失,這也是前面結(jié)構(gòu)體中的標(biāo)簽沒有定義 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")
}
運行程序,通過瀏覽器訪問 http://localhost:8080/ ,頁面顯示 “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ù)通過 GET 方法能被程序正常綁定,注意上面程序中使用了 Any() 方法,它能匹配眾多的 HTTP 方法。
如果程序繼續(xù)運行在 Debug 模式時,在命令行運行下面命令:
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
命令行的返回表明通過 POST 方法已經(jīng)成功提交請求,服務(wù)端成功返回,狀態(tài)代碼: 200 ,返回內(nèi)容: Success 。
控制臺輸出結(jié)果:
[GIN] 2019/07/13 - 17:12:37 | 200 | 0s | ::1 | POST /bindquery
從控制臺輸出可以看到,通過 POST 提交的數(shù)據(jù)沒有正常綁定。但是前面通過 ShouldBind() 方法可以正常綁定。這表明 ShouldBindQuery() 只綁定 URL Query 參數(shù)而忽略 POST 數(shù)據(jù)。
8. JSON 模型綁定
通過 POST 方法提交 JSON 格式數(shù)據(jù),程序通過綁定的方式得到 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 推斷使用哪個綁定器。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)聽并啟動服務(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ù),程序通過綁定的方式得到參數(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")
}
運行命令
curl -H "rate:300" -H "domain:music" http://localhost:8080/{"Domain":"music","Rate":300}
通過 curl 命令帶上自定義的頭部信息給 Handler 處理程序, ShouldBindHeader() 方法自動綁定頭部變量到結(jié)構(gòu)體。
?
參考:https://gitbook.cn/gitchat/column/5dab061e7d66831b22aa0b44/topic/5dab09f37d66831b22aa0b5d
總結(jié)
以上是生活随笔為你收集整理的Gin 框架学习笔记(02)— 参数自动绑定到结构体的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2022-2028年中国液晶电视市场投资
- 下一篇: 2022-2028年中国抽油烟机行业投资