Gin JSON渲染,获取参数,参数绑定大全

作者: adm 分类: go 发布时间: 2023-10-20

获取Query参数
Query参数又叫Querystring参数,是URL的?后面的一串字符串。

demo代码如下:

r.GET("/home", func(c *gin.Context) {
		username := c.Query("username")
		password := c.DefaultQuery("password", "******")
		addr := c.QueryArray("addr")
		class := c.QueryMap("class")
		age, ok := c.GetQuery("age")
    
		if ok != true {
			fmt.Println(ok)
		}

		c.JSON(http.StatusOK, gin.H{
			"username": username,
			"password": password,
			"addr":     addr,
			"class":    class,
			"age":      age,
		})
	})

结果如下:


总结:

Query()用来获取参数

使用DefaultQuery()方法时,如果没有相应的参数,就会使用defaultValue的值来代替。

QueryArray()和QueryMap()方法分别获取切片类型和字典类型的参数

GetQuery()方法返回两个值,一个value,一个bool值。当能够获取到相应的值时,bool值=true;当不能够获取到相应的值时,value为空,bool值=false。

需要注意的是切片类型的参数和字典类型的参数的写法。

切片:addr=aaa&addr=bbb
字典:class[专业]=软件工程&class[年级]=大一
获取Path参数
Path参数就是路径参数,也就是URL中斜杠和斜杠之间的参数

demo代码如下:

r.GET("/user/info/:username/:password/:hobby", func(c *gin.Context) {
		username := c.Param("username")
		password := c.Param("password")
		hobby := c.Param("hobby")
		params := c.Params

		c.JSON(http.StatusOK, gin.H{
			"username": username,
			"password": password,
			"hobby":    hobby,
			"params":   params,
		})
	})

结果如下:

总结:

把获取的Path参数的前面加上“ : ”,就表示这个Path参数是要获取的参数。

Param()方法只能一个一个的获取参数。

Params()方法是一次性获取所有的Path参数,返回的是Params类型,该类型的定义如下

type Param struct {
	Key   string
	Value string
}

type Params []Param

当有一部分Path参数获取不到时,前面获取到的Path参数都会全部丢弃。其本质原因是底层使用rang遍历所有的Path参数,如果没有相应的参数,会把整个params切片置为空。源码如下:

func (ps Params) Get(name string) (string, bool) {
   for _, entry := range ps {
      if entry.Key == name {
         return entry.Value, true
      }
   }
   return "", false //注意:并不是将entry.Value置为nil,而是将整个切片置为空。
}

func (ps Params) ByName(name string) (va string) {
   va, _ = ps.Get(name)
   return
}

func (c *Context) Param(key string) string {
	return c.Params.ByName(key)
}

获取Form表单参数
Demo代码如下:

r.POST("/info", func(c *gin.Context) {
		username := c.PostForm("username")
		password := c.DefaultPostForm("password", "******")
		hobby := c.PostFormArray("hobby")
		sex, ok := c.GetPostForm("sex")
		if ok != true {
			fmt.Println(ok)
		}

		c.JSON(http.StatusOK, gin.H{
			"username": username,
			"password": password,
			"sex":      sex,
			"hobby":    hobby,
		})
	})

结果如下:


总结:

PostForm()方法获取表单参数
使用DefaultPostForm()方法如果没有获取到参数,会有默认值代替
PostFormArray()获取数组对象的表单参数
GetPostForm()方法返回两个值,第一个是表单参数,第二个是bool值
获取Json参数
Demo代码如下:

r.POST("/json", func(c *gin.Context) {
		var m map[string]interface{}
		body, err := c.GetRawData() //从请求体(body)中获取json数据
		if err != nil {
			fmt.Println(err.Error())
		}
		err = json.Unmarshal(body, &m)
		if err != nil {
			fmt.Println(err.Error())
		}
		name := m["name"]
		email := m["email"]

		c.JSON(http.StatusOK, gin.H{
			"name":  name,
			"email": email,
		})
	})

结果如下:

总结:

GetRawData()方法是从请求体(body)中获取原始的json数据

GetRawData()底层使用ioutil包里面的ReadAll()方法来读取数据,ReadAll()方法底层使用io包里面的ReadAll()函数,ReadAll()函数的源码如下:

func ReadAll(r Reader) ([]byte, error) {
	b := make([]byte, 0, 512)
	for {
		if len(b) == cap(b) {
			// Add more capacity (let append pick how much).
			b = append(b, 0)[:len(b)]
		}
		n, err := r.Read(b[len(b):cap(b)])
		b = b[:len(b)+n]
		if err != nil {
			if err == EOF {
				err = nil
			}
			return b, err
		}
	}
}

源码分析可以看这篇文章:

io.ReadAll 怎样读全部

获取请求头中的数据
Demo代码如下:

r.GET("/header", func(c *gin.Context) {
		token := c.GetHeader("Authorization")
		c.JSON(http.StatusOK, gin.H{
			"Authorization": token,
		})
	})

结果如下:

总结:

GetHeader()方法用于获取请求头信息
设置请求头的方法有两种:

c.Header(“Authorization”, “xxx.yyy.zzz”)
c.Writer.Header().Set(“Authorization”, “xxx.yyy.zzz”)

数据绑定
基于请求的Content-Type识别请求数据类型并利用反射机制自动提取请求中QueryString、form表单、JSON、XML等参数到结构体中。 下面的示例代码演示了BindJSON()和ShouldBindJSON,它能够基于请求自动提取JSON类型的数据,并把值绑定到指定的结构体对象。

Demo代码如下:

type Login struct {
	Username string `json:"username"`
	Password string `json:"password"`
}
r.GET("/bindJson", func(c *gin.Context) {
		var login Login
		err := c.BindJSON(&login)
		if err != nil {
			fmt.Println(err.Error())
		}
		username := login.Username
		password := login.Password
		c.JSON(http.StatusOK, Login{
			Username: username,
			Password: password,
		},
		)
	})

r.GET("/shouldBindJson", func(c *gin.Context) {
		var login Login
		err := c.ShouldBindJSON(&login)
		if err != nil {
			fmt.Println(err.Error())
		}
		username := login.Username
		password := login.Password
		c.JSON(http.StatusOK, Login{
			Username: username,
			Password: password,
		},
		)
	})

结果如下:

总结:

数据绑定是利用结构体的反射机制来实现的,只要结构体里面有相应的Tag标签,就能实现对应数据类型的绑定。

ShouldBindxxx和Bindxxx区别:如果Bindxxx没有绑定到数据,会在Header中添加400的返回信息,而ShouldBindxxx不会。验证结果如下:

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!