您现在的位置是:群英 > 开发技术 > 编程语言
Gin框架中bind函数用来做什么,用法是怎样的
Admin发表于 2022-07-20 17:52:461106 次浏览
这篇文章主要介绍了title,小编觉得挺不错的,现在分享给大家,也给大家做个参考,希望大家通过这篇文章可以有所收获。

概述

Gin框架中,有bind函数可以非常方便的将url的查询参数query parameter、http的Header,body中提交上来的数据格式,如form,json,xml等,绑定到go中的结构体中去,这期间Binding做了啥事情,这么多个Bindding函数,我们该如何选择,一起通过源码来解开其中神秘的面纱吧。

Binding接口

type Binding interface {
   Name() string
   Bind(*http.Request, interface{}) error
}

Binding是一个接口,在源码中,有10个实现了Binding的结构体,以及3个接口

 

context.Bind

// Bind checks the Content-Type to select a binding engine automatically,
// Depending the "Content-Type" header different bindings are used:
//     "application/json" --> JSON binding
//     "application/xml"  --> XML binding
// otherwise --> returns an error.
// It parses the request's body as JSON if Content-Type == "application/json" using JSON or XML as a JSON input.
// It decodes the json payload into the struct specified as a pointer.
// It writes a 400 error and sets Content-Type header "text/plain" in the response if input is not valid.
func (c *Context) Bind(obj interface{}) error {
	b := binding.Default(c.Request.Method, c.ContentType())
	return c.MustBindWith(obj, b)
}

cnotext.MustBindWith

// MustBindWith binds the passed struct pointer using the specified binding engine.
// It will abort the request with HTTP 400 if any error occurs.
// See the binding package.
func (c *Context) MustBindWith(obj interface{}, b binding.Binding) error {
   if err := c.ShouldBindWith(obj, b); err != nil {
      c.AbortWithError(http.StatusBadRequest, err).SetType(ErrorTypeBind) // nolint: errcheck
      return err
   }
   return nil
}

从注解和源码可以看出,MustBindWith最终也是调用了SouldBindWith,并且对ShouldBindWith的结果进行了判断,如果有错误,则以http 400的状态码进行退出。

ShouldBindWith

// ShouldBindWith binds the passed struct pointer using the specified binding engine.
// See the binding package.
func (c *Context) ShouldBindWith(obj interface{}, b binding.Binding) error {
   return b.Bind(c.Request, obj)
}

这个方法是所有其他绑定方法的一个基础,基本上所有的绑定方法都需要用到这个方法来对数据结构进行一个绑定

以上为主要的bingding的过程,其他派生出来的如BindJSON、ShouldBindJSON等,为具体的数据类型的快捷方式而已,只是帮我们把具体的bingding的数据类型提前给封装了起来而已,如Json格式的bingding函数

context.BindJSON

// BindJSON is a shortcut for c.MustBindWith(obj, binding.JSON).
func (c *Context) BindJSON(obj interface{}) error {
   return c.MustBindWith(obj, binding.JSON)
}

context.BindJSON从源码上分析,可以看到,仅仅比Bind方法少了一句

b := binding.Default(c.Request.Method, c.ContentType())

这一句是为了判断当前的请求方法和contentType,来给context.MustBindWith传的一个具体的bingding类型。

Json的实现的Binding接口如下

func (jsonBinding) Bind(req *http.Request, obj interface{}) error {
   if req == nil || req.Body == nil {
      return fmt.Errorf("invalid request")
   }
   return decodeJSON(req.Body, obj)
}

jsonBinding结构体实现了Binding接口的Bind方法,将请求过来的Body数据进行解码,绑定到obj里面去

context.ShouldBindJSON

// ShouldBindJSON is a shortcut for c.ShouldBindWith(obj, binding.JSON).
func (c *Context) ShouldBindJSON(obj interface{}) error {
   return c.ShouldBindWith(obj, binding.JSON)
}

从源码的注解来看,ShouldBindJSON其实就是ShouldBindWith(obj, binding.JSON)的快捷方式,简单来说,就是在ShouldBindWith(obj, binding.JSON)上面固定了参数,当我们明确规定,body提交的参数内容为json时,简化了我们的调用和增强了代码的可读性。

context.ShouldBindUri()

// ShouldBindUri binds the passed struct pointer using the specified binding engine.
func (c *Context) ShouldBindUri(obj interface{}) error {
   m := make(map[string][]string)
   for _, v := range c.Params {
      m[v.Key] = []string{v.Value}
   }
   return binding.Uri.BindUri(m, obj)
}

从url绑定采用的方法跟header和body的方式不一样,不需要传入一个实现Binding接口的结构体类型

context.ShouldBindUri()

// BindUri binds the passed struct pointer using binding.Uri.
// It will abort the request with HTTP 400 if any error occurs.
func (c *Context) BindUri(obj interface{}) error {
   if err := c.ShouldBindUri(obj); err != nil {
      c.AbortWithError(http.StatusBadRequest, err).SetType(ErrorTypeBind) // nolint: errcheck
      return err
   }
   return nil
}

BindUri也是对ShouldBindUri的一个封装,多了一个对ShouldBindUri结果的一个判断 代码实例

代码如下

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)
type queryHeader struct {
	Myheader string `header:"myheader"`
	Mydemo string `header:"mydemo"`
}

type queryBody struct {
	Name string `json:"name"`
	Age int `json:"age"`
	Sex int `json:"sex"`
}

type queryParameter struct {
	Year int `form:"year"`
	Month int `form:"month"`
}

type queryUri struct {
	Id int `uri:"id"`
	Name string `uri:"name"`
}

func bindUri(context *gin.Context){
	var q queryUri
	err:= context.ShouldBindUri(&q)
	if err != nil {
		context.JSON(http.StatusBadRequest,gin.H{
			"result":err.Error(),
		})
		return
	}
	context.JSON(http.StatusOK,gin.H{
		"result":"绑定成功",
		"uri": q,
	})
}

func bindQuery(context *gin.Context){
	var q queryParameter
	err:= context.ShouldBindQuery(&q)
	if err != nil {
		context.JSON(http.StatusBadRequest,gin.H{
			"result":err.Error(),
		})
		return
	}
	context.JSON(http.StatusOK,gin.H{
		"result":"绑定成功",
		"query": q,
	})
}

func bindBody(context *gin.Context){
	var q queryBody
	err:= context.ShouldBindJSON(&q)
	if err != nil {
		context.JSON(http.StatusBadRequest,gin.H{
			"result":err.Error(),
		})
		return
	}
	context.JSON(http.StatusOK,gin.H{
		"result":"绑定成功",
		"body": q,
	})
}

func bindhead(context *gin.Context){
	var q queryHeader
	err := context.ShouldBindHeader(&q)
	if err != nil {
		context.JSON(http.StatusBadRequest,gin.H{
			"result":err.Error(),
		})
		return
	}
	context.JSON(http.StatusOK,gin.H{
		"result":"绑定成功",
		"header": q,
	})
}

func main(){
	srv := gin.Default()
	srv.GET("/binding/header",bindhead)
	srv.GET("/binding/body",bindBody)
	srv.GET("/binding/query",bindQuery)
	srv.GET("/binding/:id/:name",bindUri)
	srv.Run(":9999")
}

运行结果

绑定Header数据

绑定QueryParameter数据

绑定Body Json数据

绑定Uri数据

总结

  • 使用gin框架中的bind方法,可以很容易对http请求过来的数据传递到我们的结构体指针去,方便我们代码编程。
  • 当参数比较简单,不需要结构体来进行封装时候,此时还需采用context的其他方法来获取对应的值
  • gin在bind的时候,未对结构体的数据进行有效性检查,如果对数据有强要求时,需要自己对结构体的数据内容进行判断
  • 建议在实践过程中,使用shouldBind<xxx>函数

以上就是关于“Gin框架中bind函数用来做什么,用法是怎样的”的相关知识,感谢各位的阅读,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注群英网络,小编每天都会为大家更新不同的知识。

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。

标签: Gin框架中bind
相关信息推荐
2022-11-19 17:51:49 
摘要:组件的插槽也是为了让我们封装的组件更加具有扩展性,让使用者可以决定组件内部的一些内容到底展示什么,这篇主要介绍了增加组件扩展性的slot的相关问题,下面一起来看一下,希望对大家有帮助。
2022-07-30 17:32:05 
摘要:react可用ui组件库有:1、Material-UI,有用于布局、表单、导航、数据显示和许多其他小部件的组件;2、Ant Design,有60多个组件,带有可预测的静态类型;3、Blueprint,有40多个组件;4、React Bootstrap,提供了与大量已经存在的Bootstrap主题的完全兼容性;5、Onsen UI,提供选项卡、边菜单、堆栈导航、列表、表单等组件。
2022-09-03 17:49:42 
摘要:本篇文章带大家了解一下Bootstrap中的弹出框和提示框效果。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。
云活动
推荐内容
热门关键词
热门信息
群英网络助力开启安全的云计算之旅
立即注册,领取新人大礼包
  • 联系我们
  • 24小时售后:4006784567
  • 24小时TEL :0668-2555666
  • 售前咨询TEL:400-678-4567

  • 官方微信

    官方微信
Copyright  ©  QY  Network  Company  Ltd. All  Rights  Reserved. 2003-2019  群英网络  版权所有   茂名市群英网络有限公司
增值电信经营许可证 : B1.B2-20140078   粤ICP备09006778号
免费拨打  400-678-4567
免费拨打  400-678-4567 免费拨打 400-678-4567 或 0668-2555555
微信公众号
返回顶部
返回顶部 返回顶部