BoyChai's Blog - Gin
https://blog.boychai.xyz/index.php/tag/Gin/
-
[Go]GIN框架-请求参数
https://blog.boychai.xyz/index.php/archives/49/
2023-01-27T14:53:00+00:00
Get请求参数普通参数请求http://localhost:8080/query?id=123&name=user接收第一种方式r.GET("/query", func(context *gin.Context) {
// 获取传参
id := context.Query("id")
name := context.Query("name")
// 设置某个参数的默认值
sex := context.DefaultQuery("sex", "unknown")
// 检查address值是否传入
address, ok := context.GetQuery("address")
context.JSON(http.StatusOK, gin.H{
"id": id,
"name": name,
"sex": sex,
"address": address,
"address-ok": ok,
})
})第二种方式提前定义结构体// 定义结构体需要表示form名称,如果不标识则传参时key必须和结构体的对应的值一样比如Id就必须传入Id,id是不行的
type User struct {
Id int64 `form:"id"'`
Name string `form:"name"`
Sex string `form:"sex"`
// binding是指传参必须拥有此参数
Address string `form:"address" binding:"required"'`
}r.GET("/query", func(context *gin.Context) {
var user User
err := context.BindQuery(&user)
if err != nil {
log.Println(err)
}
context.JSON(http.StatusOK, gin.H{
"id": user.Id,
"name": user.Name,
"sex": user.Sex,
"address": user.Address,
})
})第三种方式提前定义结构体// 定义结构体需要表示form名称,如果不标识则传参时key必须和结构体的对应的值一样比如Id就必须传入Id,id是不行的
type User struct {
Id int64 `form:"id"'`
Name string `form:"name"`
Sex string `form:"sex"`
// binding是指传参必须拥有此参数
Address string `form:"address" binding:"required"'`
}r.GET("/query", func(context *gin.Context) {
var user User
err := context.ShouldBindQuery(&user)
if err != nil {
log.Println(err)
}
context.JSON(http.StatusOK, gin.H{
"id": user.Id,
"name": user.Name,
"sex": user.Sex,
"address": user.Address,
})
})返回值第一种方式状态码200{
"address": "",
"address-ok": false,
"id": "123",
"name": "user",
"sex": "unknown"
}第二种方式状态码400后台会报:2023/01/27 22:18:55 Key: 'User.Address' Error:Field validation for 'Address' failed on the 'required' tag
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 200{
"address": "",
"id": 123,
"name": "user",
"sex": ""
}第三种方式状态码200后台会报:2023/01/27 22:19:33 Key: 'User.Address' Error:Field validation for 'Address' failed on the 'required' tag{
"address": "",
"id": 123,
"name": "user",
"sex": ""
}数组参数请求http://localhost:8080/query?address=beijing&address=qingdao接收第一种方式r.GET("/query", func(context *gin.Context) {
address := context.QueryArray("address")
context.JSON(http.StatusOK, address)
})第二种方式提前定义结构体type Address struct {
Address []string `form:"address"`
}r.GET("/query", func(context *gin.Context) {
var address Address
err := context.BindQuery(&address)
if err != nil {
log.Println(err)
}
context.JSON(http.StatusOK, address)
})第三种方式提前定义结构体type Address struct {
Address []string `form:"address"`
}r.GET("/query", func(context *gin.Context) {
var address Address
err := context.ShouldBindQuery(&address)
if err != nil {
log.Println(err)
}
context.JSON(http.StatusOK, address)
})返回值第一种方式状态码200[
"beijing",
"qingdao"
]第二种方式状态码200{
"Address": [
"beijing",
"qingdao"
]
}第三种方式状态码200{
"Address": [
"beijing",
"qingdao"
]
}map参数请求http://localhost:8080/query?addressMap[home]=beijing&addressMap[company]=qingdao接收r.GET("/query", func(context *gin.Context) {
addressMap := context.QueryMap("addressMap")
context.JSON(http.StatusOK, addressMap)
})返回值状态码200{
"company": "qingdao",
"home": "beijing"
}POST请求post请求一般是表单参数和json参数表单请求请求http://localhost:8080/queryform-dataid=123
name=user
address=beijing
address=qingdao
addressMap[home]=beijing
addressMap[company]=qingdao接收r.POST("/query", func(context *gin.Context) {
id := context.PostForm("id")
name := context.PostForm("name")
address := context.PostFormArray("address")
addressMap := context.PostFormMap("addressMap")
context.JSON(http.StatusOK, gin.H{
"id": id,
"name": name,
"address": address,
"addressMap": addressMap,
})
})PS:接收也可以使用func (c *gin.Context) ShouldBind(obj any) error {}函数进行接收和上面get讲的差不多一样这里不再讲解返回值状态码200{
"address": [
"beijing",
"qingdao"
],
"addressMap": {
"company": "qingdao",
"home": "beijing"
},
"id": "123",
"name": "user"
}JSON请求请求http://localhost:8080/queryraw or json{
"address": [
"beijing",
"qingdao"
],
"addressMap": {
"company": "qingdao",
"home": "beijing"
},
"id": 123,
"name": "user",
"sex":"Male"
}接收定义结构体,接收json数据结构体不需要加form表示,接收时会自动把Name转换为name进行匹配接收或者添加json的标识进行匹配type User struct {
Id int64 `json:"id"`
Name string
Sex string
Address []string
AddressMap map[string]string
} r.POST("/query", func(context *gin.Context) {
var user User
err := context.ShouldBindJSON(&user)
if err != nil {
log.Println(err)
}
context.JSON(http.StatusOK, user)
})返回值状态码200{
"Id": 123,
"Name": "user",
"Sex": "Male",
"Address": [
"beijing",
"qingdao"
],
"AddressMap": {
"company": "qingdao",
"home": "beijing"
}
}文件请求代码实现r.POST("/save", func(context *gin.Context) {
form, err := context.MultipartForm()
if err != nil {
log.Println(err)
}
for _, fileArray := range form.File {
for _, v := range fileArray {
context.SaveUploadedFile(v, "./"+v.Filename)
}
}
context.JSON(http.StatusOK, form.Value)
})context.MultipartForm()返回的from里面有俩值,一个是文件数组,还有一个是提交的参数。上传好的文件会被context.SaveUploadedFile保存到本地
-
[Go]GIN框架-路由
https://blog.boychai.xyz/index.php/archives/48/
2023-01-19T14:55:00+00:00
路由概述路由(Routing)是由一个 URI(或者叫路径)和一个特定的 HTTP 函数(GET、POST 等)组成的,涉及到应用如何响应客户端对某个网站节点的访问。RESTful APIRESTful API 是目前比较成熟的一套互联网应用程序的 API 设计理论,所以我们设计我们的路由的时候建议参考 RESTful API 指南。在 RESTful 架构中,每个网址代表一种资源,不同的请求方式表示执行不同的操作:请求方式操作GET(SELECT)从服务器中获取资源POST(CREATE)在服务器中创建资源PUT(UPDATE)在服务器中更新更改资源DELETE(DELETE)在服务器中删除资源创建路由GET// GET
r.GET("/GET", func(c *gin.Context) {
c.String(http.StatusOK, "GET")
})POST// POST
r.POST("/POST", func(c *gin.Context) {
c.String(http.StatusOK, "POST")
})PUT// PUT
r.PUT("/PUT", func(c *gin.Context) {
c.String(http.StatusOK,"PUT")
})DELETE// DELETE
r.DELETE("/DELETE", func(c *gin.Context) {
c.String(http.StatusOK, "DELETE")
})其他创建方法所有类型如果同一个地址想要所有类型的请求都支持使用那么可以通过下面代码进行创建// 接收所有类型请求
r.Any("/Any", func(c *gin.Context) {
c.String(http.StatusOK, "Any")
})两个或多个// 先创建一个方法
func requestReturn(c *gin.Context) {
c.String(http.StatusOK, "OTHER")
}
// 在创建请求URL
r.GET("/OTHER", requestReturn)
r.POST("/OTHER", requestReturn)URI静态URIr.GET("/user/find", func(c *gin.Context) {
c.String(http.StatusOK, "any")
})路径参数r.GET("/user/find/:id", func(c *gin.Context) {
c.String(http.StatusOK, c.Param("id"))
})模糊参数// 使用path来接收值
r.GET("/user/*path", func(c *gin.Context) {
c.String(http.StatusOK, c.Param("path"))
})路由分组在实际开发中,路由可能会有很多的版本,为了方便开发管理可以使用以下方法进行分组创建// 路由分组
v1 := r.Group("v1")
v2 := r.Group("v2")
v1.GET("/user/find", func(c *gin.Context) {
c.String(http.StatusOK, "/v1/user/find")
})
v2.GET("/user/find", func(c *gin.Context) {
c.String(http.StatusOK, "/v2/user/find")
})