浅谈Gin框架中bind的使用

 更新时间:2021年12月10日 15:34:14   作者:xiaojinran  
Gin框架中有bind函数,可以非常方便的将url的查询参数query parameter、http的Header,body中提交上来的数据格式,本文就详细的介绍Gin框架中bind的使用,感兴趣的可以了解一下

概述

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的使用的文章就介绍到这了,更多相关Gin框架中bind内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Golang Gorm实现自定义多态模型关联查询

    Golang Gorm实现自定义多态模型关联查询

    GORM 是一个流行的开源 ORM (Object-Relational Mapping) 库,专为 Go 语言设计,它简化了与 SQL 数据库的交互,GORM 封装了数据库操作,使得开发者能够通过简单的链式调用来执行 CRUD,本文给大家介绍了Golang Gorm实现自定义多态模型关联查询,需要的朋友可以参考下
    2024-11-11
  • golang字符串切片去重的几种算法

    golang字符串切片去重的几种算法

    这篇文章主要介绍了golang字符串切片去重的几种算法的相关资料,需要的朋友可以参考下
    2023-09-09
  • go并发利器sync.Once使用示例详解

    go并发利器sync.Once使用示例详解

    这篇文章主要为大家介绍了go并发利器sync.Once使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • go换国内源的方法步骤

    go换国内源的方法步骤

    在中国境内,由于网络原因,直接下载Go语言的包可能会遇到速度慢或下载失败的问题,可以使用国内的Go模块代理来加速下载速度,本文就来介绍一下go换国内源的方法步骤,感兴趣的可以了解一下
    2024-09-09
  • Go语言中两个比较流行的缓存库使用示例

    Go语言中两个比较流行的缓存库使用示例

    缓存是计算机科学中的一个重要概念,设想某个组件需要访问外部资源,它向外部源请求资源,接收并使用资源,这些步骤都需要花费时间,下面这篇文章主要给大家介绍了关于Go语言中两个比较流行的缓存库使用的相关资料,需要的朋友可以参考下
    2024-04-04
  • Go语言实现的web爬虫实例

    Go语言实现的web爬虫实例

    这篇文章主要介绍了Go语言实现的web爬虫,实例分析了web爬虫的原理与Go语言的实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-02-02
  • Go语言实现二分查找方法示例

    Go语言实现二分查找方法示例

    这篇文章主要为大家介绍了Go语言实现二分查找方法示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • 用Go获取短信验证码的示例代码

    用Go获取短信验证码的示例代码

    要用Go获取短信验证码,通常需要连接到一个短信服务提供商的API,并通过该API发送请求来获取验证码,由于不同的短信服务提供商可能具有不同的API和授权方式,我将以一个简单的示例介绍如何使用Go语言来获取短信验证码,需要的朋友可以参考下
    2023-07-07
  • Go string转int,int64,int32及注意事项说明

    Go string转int,int64,int32及注意事项说明

    这篇文章主要介绍了Go string转int,int64,int32及注意事项说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • golang 实现两个结构体复制字段

    golang 实现两个结构体复制字段

    这篇文章主要介绍了golang 实现两个结构体复制字段,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04

最新评论