Analysis of binding implementation process of gin golang web development model

Time:2021-3-13

We learned that gin can obtain the parameters submitted by the front end through methods like defaultquery or defaultpostform. It’s also easy to use when there are not many parameters, but think about it. If you use this method when the interface has many parameters, you will call the method to get parameters many times. This paper will introduce a new method to receive parameters to solve this problem: model binding.

The model binding in gin can be understood as mapping a request parameter to a specific type. Gin supports various parameter formats such as JSON, XML, yaml and form parameters, and only needs to declare labels on corresponding fields.

Binding form or query string


type Person struct {
	Name  string `form:"name"`
	Address string `form:"address"`
}

func startPage(c *gin.Context) {
	var person Person
	if c.ShouldBindQuery(&person) == nil {
		log.Println(person.Name)
		log.Println(person.Address)
	}
	c.String(200, "Success")
}

Declare the form label in the name field of the structure and call the shouldbindquery method. Gin will bind the name and address parameters in the query string for us. Note that although we declare the form tag, shouldbindquery only binds the parameters in the query string.

If you want to bind the parameters in the form, you don’t need to change the structure. You need to change the shouldbindquery side to the shouldbind method. Shouldbind method will distinguish between get and post requests. If it is a get request, it will bind the parameters in the query string. If it is a post request, it will bind the contents in the form parameters. However, it cannot bind both parameters at the same time.

Binding JSON parameters


type Person struct {
	Name  string `json:"name"`
	Address string `json:"address"`
}

func startPage(c *gin.Context) {
	var person Person
	if c.ShouldBind(&person) == nil {
		log.Println(person.Name)
		log.Println(person.Address)
	}
	c.String(200, "Success")
}

JSON is a common data exchange format, especially when interacting with web front-end pages, it seems to have become a de facto standard. The method of binding JSON format data with gin is very simple. You only need to set the label of the field to JSON and call shouldbind method.

Other type parameter binding

Set the label of routing parameter to URI when binding, and call shouldbinduri method.


type Person struct {
	Id  string `uri:"id"`
}

func startPage(c *gin.Context) {
	var person Person
	if c.ShouldBindUri(&person) == nil {
		log.Println(person.Id)
	}
	c.String(200, "Success")
}

For the parameter bound in HTTP header, the label of the field is set to header, and the calling method is shouldbindheader.

Another less commonly used array parameter is that the field label is set to form: “colors [] and the structure example is as follows:


type myForm struct {
  Colors []string `form:"colors[]"`
}

In the scene of file upload, I rarely use model binding to obtain parameters. In gin, model binding support is also provided for this kind of scene.

type ProfileForm struct {
	Name  string        `form:"name"`
	Avatar *multipart.FileHeader `form:"avatar"`
	// Avatars []* multipart.FileHeader  `Form: "Avatar" ` multi file upload
}

func main() {
	router := gin.Default()
	router.POST("/profile", func(c *gin.Context) {
		var form ProfileForm
		if err := c.ShouldBind(&form); err != nil {
			c.String(http.StatusBadRequest, "bad request")
			return
		}

		err := c.SaveUploadedFile(form.Avatar, form.Avatar.Filename)
		if err != nil {
			c.String(http.StatusInternalServerError, "unknown error")
			return
		}

		c.String(http.StatusOK, "ok")
	})
	router.Run(":8080")
}

Multiple types of model binding

If we have an updateuser interface, put / user /: ID, the parameter is {“nickname”: “nickname…”, “mobile”: “133223232”}. The code is as follows:

type ProfileForm struct {
	Id    int  `uri:"id"`
	Nickname string ` JSON: "nickname" '// nickname
	Mobile string ` JSON: "mobile" '// mobile number
}

func main() {
	router := gin.Default()
	router.GET("/user/:id", func(c *gin.Context) {
		var form ProfileForm
		if err := c.ShouldBindUri(&form); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}

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

		c.String(http.StatusOK, "ok")
	})
	router.Run(":8080")
}

The code calls the bind method twice to get all the parameters. After communicating with the gin community, we found that it is not possible to call a method to bind multiple parameter sources at the same time. The current gin version is 1.6. X. I don’t know whether this function will be provided in the future.

The above is the whole content of this article, I hope to help you learn, and I hope you can support developer more.