Gin中数据解析和绑定的几种方法实现
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">概要</a></li><li><a href="#_label1">Json数据解析和绑定</a></li><ul class="second_class_ul"><li><a href="#_lab2_1_0">代码实现</a></li><li><a href="#_lab2_1_1">注意:</a></li><li><a href="#_lab2_1_2">测试</a></li></ul><li><a href="#_label2">表单数据解析和绑定</a></li><ul class="second_class_ul"><li><a href="#_lab2_2_3">前端实现</a></li><li><a href="#_lab2_2_4">后端实现</a></li><li><a href="#_lab2_2_5">注意</a></li><li><a href="#_lab2_2_6">测试</a></li></ul><li><a href="#_label3">URI数据解析和绑定</a></li><ul class="second_class_ul"><li><a href="#_lab2_3_7">代码实现</a></li><li><a href="#_lab2_3_8">注意</a></li><li><a href="#_lab2_3_9">测试</a></li></ul><li><a href="#_label4">小结</a></li><ul class="second_class_ul"></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>概要</h2><p>Gin数据解析和绑定可以分为三类</p>
<ul><li>Json数据的解析和绑定</li><li>表单数据的解析和绑定</li><li>URI数据的解析和绑定</li></ul>
<p>我们来分别讲解各自的数据类型以及对应的绑定和解析</p>
<p class="maodian"><a name="_label1"></a></p><h2>Json数据解析和绑定</h2>
<blockquote><p>Json数据要解析到结构体时,需要在结构体标签中用到json标签,用于序列化Json数据并对应到结构体中</p></blockquote>
<p>我们使用Context包下的<code>ShouldBindJSON()</code>方法将请求中传递的Json数据解析到结构体中</p>
<p class="maodian"><a name="_lab2_1_0"></a></p><p class="maodian"><a name="_lab2_3_7"></a></p><h3>代码实现</h3>
<div class="jb51code"><pre class="brush:go;">type Login struct {
Username string `json:"username" form:"username" binding:"required"`
Password string `json:"password" form:"password" binding:"required"`
}
func main() {
r := gin.Default()
r.POST("/login", func(c *gin.Context) {
var form Login
if err := c.ShouldBind(&form); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if form.Username != "root" || form.Password != "root" {
c.JSON(http.StatusBadRequest, gin.H{"error": "304"})
return
}
c.JSON(http.StatusOK, gin.H{"data": form})
})
r.Run(":8080")
}
}
</pre></div>
<p class="maodian"><a name="_lab2_1_1"></a></p><h3>注意:</h3>
<blockquote><p>在结构体定义的时候一定要带上json标签,json标签的作用是让发送的json字符串数据能够对应到结构体字段上。</p></blockquote>
<blockquote><p>ShouldBindJSON()的作用是什么?该方法可以将前端传递的json格式数据自动解析到结构体上,并配合结构体中的json标签进行精准映射,简化了数据绑定过程</p></blockquote>
<p class="maodian"><a name="_lab2_1_2"></a></p><p class="maodian"><a name="_lab2_2_6"></a></p><p class="maodian"><a name="_lab2_3_9"></a></p><h3>测试</h3>
<p>这里我使用的工具是ApiFox<br />在工具中发送post请求,这里我们需要使用json格式发送,不能用query参数</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202511/2025112110310521.png" /></p>
<p class="maodian"><a name="_label2"></a></p><h2>表单数据解析和绑定</h2>
<p><code>什么是表单数据?很简单,就是前端使用表单组件来提交数据的格式</code><br />表单数据也是键值对形式存储的,并且不支持嵌套。 <code>username=root&password=root</code></p>
<p class="maodian"><a name="_lab2_2_3"></a></p><h3>前端实现</h3>
<div class="jb51code"><pre class="brush:xhtml;"><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form action="http://localhost:8080/login" method="post" enctype="application/x-www-form-urlencoded">
用户名<input type="text" name="username">
密码<input type="password" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>
</pre></div>
<p>这里指定了表单的编码方式为<code>enctype="application/x-www-form-urlencoded"</code></p>
<p class="maodian"><a name="_lab2_2_4"></a></p><h3>后端实现</h3>
<p>这里我们可以使用<code>ShouldBind()</code>或者<code>Bind()</code>方法进行数据解析</p>
<div class="jb51code"><pre class="brush:go;">type Login struct {
Username string `form:"username" json:"username" binding:"required"`
Password string `form:"password" json:"password" binding:"required"`
}
func main() {
r := gin.Default()
r.POST("/login", func(c *gin.Context) {
var form Login
fmt.Println(form)
if err := c.ShouldBind(&form); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if form.Username != "root" || form.Password != "root" {
c.JSON(http.StatusBadRequest, gin.H{"error": "304"})
return
}
c.JSON(http.StatusOK, gin.H{"data": form})
})
r.Run(":8080")
}
</pre></div>
<p class="maodian"><a name="_lab2_2_5"></a></p><p class="maodian"><a name="_lab2_3_8"></a></p><h3>注意</h3>
<blockquote><p>注意结构体的标签中使用form标签,这样配合ShouldBind()方法可以将表单数据解析到结构体并对应到相应字段上</p></blockquote>
<h3>测试</h3>
<p>打开本地创建的html文件,将前端代码复制到文件中,保存后在浏览器中打开</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202511/2025112110310535.png" /></p>
<p>这里我们的用户名和密码都是root<br />发送请求后,页面应该响应出来一个json格式的数据</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202511/2025112110310555.png" /></p>
<p>至于错误的用户名和密码是什么效果,可以自行测试</p>
<p class="maodian"><a name="_label3"></a></p><h2>URI数据解析和绑定</h2>
<p><code>什么是URI?注意是uri,不是url。url是uri的子集,这里我们只需要知道uri可以是url,也就是我们访问资源的时候,斜杠后边的内容,即访问路径。</code></p>
<blockquote><p>比如<code>localhost:8080/login/root/root</code>,这时候可以把uri看成url,并且我们可以通过shouldBindUri()将路径中的两个root进行数据解析,解析到Login结构体中,并且通过结构体中的uri标签,将数据映射到对应的结构体字段上。</p></blockquote>
<h3>代码实现</h3>
<div class="jb51code"><pre class="brush:go;">type Login struct {
Username string `form:"username" json:"username" uri:"username" binding:"required"`
Password string `form:"password" json:"password" uri:"password" binding:"required"`
}
func main() {
r := gin.Default()
r.GET("/:username/:password", func(c *gin.Context) {
var form Login
if err := c.ShouldBindUri(&form); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if form.Username != "root" || form.Password != "root" {
c.JSON(http.StatusBadRequest, gin.H{"status": 304})
return
}
c.JSON(http.StatusOK, gin.H{"status": 200})
})
r.Run(":8080")
}
</pre></div>
<h3>注意</h3>
<blockquote><p>结构体中要带上uri标签,这样可以结合ShouldBindUri进行数据绑定的简化</p></blockquote>
<h3>测试</h3>
<p>我们打开浏览器,输入<code>localhost:8080/root/root</code>,这里和我们的代码中定义的路径对应,代码中没有写<code>login/:username/:password</code>那我们请求时也不带login,并且代码中定义的只返回一个200状态码,这些内容都可以根据实际情况进行更改</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202511/2025112110310581.png" /></p>
<p>此时,三种类型的数据解析和绑定我们就都测试完毕</p>
<p class="maodian"><a name="_label4"></a></p><h2>小结</h2>
<p>从上边的三个demo可以看到,gin处理这些不同类型的数据对应了不同的方法,我们需要使用正确的方法进行处理,保证了代码的灵活性,也可以减少错误率</p>
頁:
[1]