Introduction
In the Gin
framework, parameters can receive a key by designation and are directly bound to the structure. Let’s explain how it happens:
Binding method
Two types of binding methods exist in the Gin
framework, Must bind
and Should bind
, and the corresponding methods of these two types are as follows:
Function | Must bind method |
Should bind method |
---|---|---|
Bind |
ShouldBind |
|
JSON bind |
BindJSON |
ShouldBindJSON |
XML bind |
BindXML |
ShouldBindXML |
GET bind |
BindQuery |
ShouldBindQuery |
YAML bind |
BindYAML |
ShouldBindYAML |
MustBindWith and ShouldBindWith
Bind*
A type’s method is an MustBindWith
encapsulation; Should*
a type’s method is ShouldBindWith
an encapsulation;
- Binding syntax
Define the bound structure
type StructName struct {
Xxx type `form:"paramName" binding:"required"`
}
Label Description:
form:"paramName"
: paramName is the name of the parameter;binding:"required"
: means that the field must be bound;
Bind the uri parameter
By using the function BindQuery
and ShouldBindQuery
, used to bind only GET
the parameters in the request uri
, such as: /funcName?a=x&b=x.
- Code
//--------- main.go ---------------
package main
import (
"fmt"
"go_use/practise" // Code sample package
"github.com/gin-gonic/gin" // Import Gin framework
)
func main() {
engine := gin.Default()
practise.TestBindQuery(engine)
_ = engine.Run(":9090")
}
//------ go_use/practise/param_bind.go -------
// define structure
type UriParam struct {
Name string `form:"name" binding:"required"`
Age int `form:"age"`
Home string `form:"home"`
}
// bind GET(BindQuery and 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})
})
}
- Request
# All parameters are passed
$ curl -X GET http://127.0.0.1:9090/bindQuery?age=25&name=Marsero&home=Mars&type=1
{"result":{"Name":"Marsero","Age":25,"Home":"Mars"}}
$ curl -X GET http://127.0.0.1:9090/bindQuery?age=25&name=Marsero&home=Mars&type=2
{"result":{"Name":"Marsero","Age":25,"Home":"Mars"}}
# If the required parameter name is not filled in, an error will be reported➜
curl -X GET http:// 127.0.0.1:9090/bindQuery?age=25&home=Mars&type=2
{"error":"Key: 'UriParam.Name' Error:Field validation for 'Name' failed on the 'required' tag"}
Bind JSON
Use functions BindJSON
and ShouldBindJSON
to bind submitted JSON
parameter information.
- Code
//--------- main.go ---------------
package main
import (
"fmt"
"go_use/practise" // code sample package
"github.com/gin-gonic/gin" // Import Gin framework
)
func main() {
engine := gin.Default()
practise.TestBindJson(engine)
_ = engine.Run(":9090")
}
//------ go_use/practise/param_bind.go -------
// Define the JSON structure to be bound
type Param struct {
Name string `json:"name"`
Age int ` json:"age"`
Likes []string `json:"likes"`
}
// Bind the submitted Json data
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})
})
}
- Request
# raw JSON code in the body
# {
# "name":"Marsero",
# "age":"25",
# "likes":["books","traveling"],
# }
$ curl -X POST http://127.0.0.1:9090/bindJSON?type=1
{"result":{"name":"Marsero","age":25,"likes":["books","traveling"]}}
Binding XML
Use functions BindXML
and ShouldBindXML
to bind submitted XML
parameter information.
- Code
//--------- main.go ---------------
package main
import (
"go_use/practise" // code sample package
"github.com/gin-gonic/gin" // Import Gin framework
)
func main() {
engine := gin.Default()
practise.TestBindXml(engine)
_ = engine.Run(":9090")
}
//------ go_use/practise/param_bind.go -------
// Modify the JSON structure to be bound, add XML tag
type Param struct {
Name string `json:"name" xml:"name"`
Age int `json:"age" xml:"age"`
Likes []string `json:"likes" xml:"likes"`
}
// Bind Xml information
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})
})
}
- Request
# raw XML code in the body
# <?xml version="1.0" encoding="UTF-8"?>
# <root>
# <name>Marsero</name>
# <name>25</name>
# <likes>books</likes>
# <likes>traveling</likes>
# </root>
$ curl -X POST http://127.0.0.1:9090/bindXML?type=2
{"result":{"name":"Marsero","age":25,"likes":["books","traveling"]}}
Binding request.Body
c.Request.Body
Cannot be called multiple times, after the first binding c.Request.Body
will be set to EOF.
- Error example
//--------- main.go ---------------
package main
import (
"go_use/practise" // code sample package
"github.com/gin-gonic/gin" // Import Gin framework
)
func main() {
engine := gin.Default()
practise.TestBindXml(engine)
_ = engine.Run(":9090")
}
//------ go_use/practise/param_bind.go -------
type BodyAParam struct {
Name string `json:"name"`
}
type BodyBParam struct {
Home string `json:"home"`
}
// Repeat binding request.Body (error example)
func TestBindBody(engine *gin.Engine) {
engine.POST("/body", func(context *gin.Context) {
paramA := BodyAParam{}
paramB := BodyBParam{}
// c.ShouldBind uses c.Request.Body, which is not reusable.
_ = context.ShouldBindJSON(¶mA)
// Since c.Request.Body is EOF now, an error will be reported here.
_ = context.ShouldBindJSON(¶mB)
context.JSON(200, gin.H{"paramA": paramA, "paramB": paramB})
})
}
- Request to return
# Found that only paramA was successfully bound
$ curl -X POST http://127.0.0.1:9090/body -d '{"name":"Marsero","home":"Mars"}'
{"paramA":{"name":"Marsero"},"paramB":{"home":"Mars"}}
- Correct example
//--------- main.go ---------------
package main
import (
"go_use/practise" // code sample package
"github.com/gin-gonic/gin" // Import Gin framework
)
func main() {
engine := gin.Default()
practise.TestBindXml(engine)
_ = engine.Run(":9090")
}
//------ go_use/practise/param_bind.go -------
type BodyAParam struct {
Name string `json:"name"`
}
type BodyBParam struct {
Home string `json:"home"`
}
// Repeat binding request.Body (correct example)
func TestBindBody2(engine *gin.Engine) {
engine.POST("/body2", func(context *gin.Context) {
paramA := BodyAParam{}
paramB := BodyBParam{}
// Read c.Request.Body and store the result in the context.
_ = context.ShouldBindBodyWith(¶mA, binding.JSON)
// At this time, reuse the body stored in the context.
_ = context.ShouldBindBodyWith(¶mB, binding.JSON)
context.JSON(200, gin.H{"paramA": paramA, "paramB": paramB})
})
}
- Request to return
# Both paramA and paramB are successfully bound
$ curl -X POST http://127.0.0.1:9090/body2 -d '{"name":"Marsero","home":"Mars"}'
{"paramA":{"name":"Marsero"},"paramB":{"home":"Mars"}}