gin框架中可以非常方便的将http请求的form数据,和路由参数中的uri 数据通过反射的方式将我们自定义在结构体中的TAG字段和请求参数中同名的数据进行绑定。
要完成数据的绑定, 首先我们需要定义一个结构体和需要绑定的结构体字段,并在结构体字段中使用TAG标记当前字段需要和那个请求参数进行绑定,方法如下:
1. 请求表单form中的数据绑定至自定义结构体
要将请求form中的数据【包含,get, post,请求头HEADER中的数据等】绑定到自定义的结构体中, form类型的数据绑定使用tag form来进行标记绑定关系。
- 结构体定义
type MyDiy struct {Page int `json:"page" form:"page,default=1"` // 这里将表单中的form 和这里的Page字段进行绑定,如果表单中没有page字段则设置默认值为1Size int `json:"size" form:"size,default=10"`Total int `form:"total"` // 这里将表单中的total和这里的Total进行绑定,注意 这里的total名字可以随意,只要和表单中的对应即可CreatedAt time.Time `form:"created_at" time_format:"2006-01-02T15:04:05Z07:00" time_utc:"1"`
}
结构体Tag标签定义说明
结构体的TAG标签定义是在结构体字段后面使用 多行字符串符号 `内容 ` 来包括。 在这里可以定义多个tag内容, 多个tag使用空格分隔。
这里的 json:"xxx" 定义是给json序列化时使用的标签,可以省略;
form表单绑定HTML 复选框
form后面定义的是我们进行form绑定用的字段信息的定义, 如: form:"name" 这里的name即是你要和你提交的表单信息绑定对应的name, 如果你的前端提交的是一个 HTML 复选框,的数据,那么你的HTML 复选框的名字就是 类似 name[] 这样的,如:前端表单数据是这样的 <input type="checkbox" name="colors[]" value="red" id="red"> , 那这里的 name 就是 colors[] 这样就可以获取到你前端提交的所有复选框的内容
form绑定默认值设置: 在form定义里面使用逗号分隔后指定default=xxx
Page int `json:"page" form:"page,default=1"` 这个表示将当前的结构体的 Page 字段在form绑定的时候使用 page这个名称和请求参数中的 page参数的值进行绑定, 如果请求参数中没有page字段,则将default定义的值设置为page的默认值。
form绑定时间格式设置
CreatedAt time.Time `form:"created_at" time_format:"2006-01-02T15:04:05Z07:00" time_utc:"1"` 这个的意思就是将请求参数中的 created_at字段和这里的 CreatedAt进行绑定,同时设置了时间的格式为"2006-01-02T15:04:05Z07:00" 【time.RFC3339】, 如果不指定则默认的时间格式为time.RFC3339, 如果表单中的created_at 时间是一个数字时间戳,则这里的格式就需要指定是 "unix" 秒的时间戳 还是 "unixnano" 纳秒时间戳 ,
time_utc:"1" 表示指定当前的时间是UTC时间, 0表示不是UTC时间, 这个地方的值会被解析为一个布尔值。
对于时间格式,这里还可以有一个tag可设置,即 time_location 用来设置本地时间, 详见 time.LoadLocation(name string) , 如: time_location:"PRC" 这个就表示当前时间为中国时间
CreatedAt time.Time `form:"created_at" time_format:"2006-01-02T15:04:05Z07:00" time_utc:"1" time_location:"PRC"`
-
form数据绑定示例
package mainimport ("log""time""github.com/gin-gonic/gin"
)type MyDiy struct {Page int `json:"page" form:"page"` // 这里将表单中的form 和这里的Page字段进行绑定Size int `json:"size" form:"size,default=10"` // 带默认值 ,如果表单中没有size字段则设置默认值为10Total int `form:"-"` // 这里的 - 表示对当前字段忽略form的绑定CreatedAt time.Time `form:"created_at" time_format:"2006-01-02T15:04:05Z07:00" time_utc:"1"` // 时间类型绑定,同时还指定了时间布局格式 和是否utc时间
}func main() {route := gin.Default()route.GET("/diy", startPage)route.Run(":8080")
}func startPage(c *gin.Context) {var diy MyDiy// 如果是 `GET` 请求,只使用 `Form` 绑定引擎(`query`)。// 如果是 `POST` 请求,首先检查 `content-type` 是否为 `JSON` 或 `XML`,然后再使用 `Form`(`form-data`)。if c.ShouldBind(&diy) == nil {log.Println(diy.Page)log.Println(diy.Size)log.Println(diy.CreatedAt)}c.String(200, "Success")
}
这时我们只要访问 http://localhost:8080/?page=1&cteated_at=2024-07-01T14:51:58 就会将当前的参数page,cteated_at的数据自动绑定到我们定义的结构体MyDiy上面, 我们这里没有传递参数 size 就会使用我们在结构体TAG里面定义的默认值 10班的到MyDiy上面。
2. 路由参数uri的参数绑定
uri的参数绑定相对于form绑定而已较为简单,请看一下示例:
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() {r := gin.Default()r.GET("/:name/:id", func(c *gin.Context) {var person Personif err := c.ShouldBindUri(&person); err != nil {c.JSON(400, gin.H{"msg": err.Error()})return}c.JSON(200, gin.H{"name": person.Name, "uuid": person.ID})})r.Run(":8088")
}
总结:
gin框架中的数据绑定的难点就在于结构体标签TAG的定义, form的绑定使用 form:"xxx"来定义, uri的绑定使用 uri:"xxx"来定义。 uri的绑定和form表单绑定的区别就是在定义结构体标签的事后他们采用的标签名称不同。还有他们绑定的数据源不同而已。 uri绑定的是uri中的路由定义参数, form绑定的是http的请求参数,包含get, post, 上传数据, 还有http请求的头部header数据。