gin的url查询参数解析
gin作为go语言最知名的网络库,在这里我简要介绍一下url的查询参数解析。主要是这里面存在一些需要注意的地方。这里,直接给出代码,和运行结果,在必要的地方进行分析。
代码1:
type StructA struct {
FieldA string `form:"field_a"`
}
type StructB struct {
NestedStruct StructA
FieldB string `form:"field_b"`
}
type StructC struct {
NestedStructPointer *StructA
FieldC string `form:"field_c"`
}
func GetDataB(c *gin.Context) {
var b StructB
c.Bind(&b)
c.JSON(200, gin.H{
"a": b.NestedStruct,
"b": b.FieldB,
})
}
func GetDataC(c *gin.Context) {
var b StructC
c.Bind(&b)
c.JSON(200, gin.H{
"a": b.NestedStructPointer,
"c": b.FieldC,
})
}
func main() {
r := gin.Default()
r.GET("/getb", GetDataB)
r.GET("/getc", GetDataC)
r.Run()
}
测试结果:
$ curl "http://localhost:8080/getb?field_a=hello&field_b=world"上述结果显示gin的query解析可以嵌套赋值,只需要form tag和传入的参数一致。
{"a":{"FieldA":"hello"},"b":"world"}
$ curl "http://localhost:8080/getc?field_a=hello&field_c=world"
{"a":{"FieldA":"hello"},"c":"world"}
再看下面的代码:
代码2:
package main import (
"github.com/gin-gonic/gin"
) type StructA struct {
FieldA string `form:"field_a"`
} type StructB struct {
StructA
FieldB string `form:"field_b"`
} type StructC struct {
*StructA
FieldC string `form:"field_c"`
} func GetDataB(c *gin.Context) {
var b StructB
c.Bind(&b)
c.JSON(200, gin.H{
"a": b.FieldA,
"b": b.FieldB,
})
} func GetDataC(c *gin.Context) {
var b StructC
c.Bind(&b)
c.JSON(200, gin.H{
"a": b.FieldA,
"c": b.FieldC,
})
} func main() {
r := gin.Default()
r.GET("/getb", GetDataB)
r.GET("/getc", GetDataC) r.Run()
}
输出结果:
curl "http://localhost:8080/getb?field_a=hello&field_b=world"
{"a":"hello","b":"world"}
curl "http://localhost:8080/getc?field_a=hello&field_c=world"
{"a":"hello","c":"world"}
结果显示,gin的url查询参数解析可以正常处理嵌套的结构体,只需要form tag和传入的参数一致。
再看下面代码:
代码3:
package main import (
"github.com/gin-gonic/gin"
) type structA struct {
FieldA string `form:"field_a"`
} type StructB struct {
structA
FieldB string `form:"field_b"`
} type StructC struct {
*structA
FieldC string `form:"field_c"`
} func GetDataB(c *gin.Context) {
var b StructB
c.Bind(&b)
c.JSON(200, gin.H{
"a": b.FieldA,
"b": b.FieldB,
})
} func GetDataC(c *gin.Context) {
var b StructC
c.Bind(&b)
c.JSON(200, gin.H{
"a": b.FieldA,
"c": b.FieldC,
})
} func main() {
r := gin.Default()
r.GET("/getb", GetDataB)
r.GET("/getc", GetDataC) r.Run()
}
注意,上述代码只是将StructA改为structA,也就是说大小写变化。测试结果如下:
curl "http://localhost:8080/getb?field_a=hello&field_b=world"
{"a":"","b":"world"}
curl "http://localhost:8080/getc?field_a=hello&field_c=world"
客户端显示为空,服务器打印一个panic语句,错误类型是runtime error: invalid memory address or nil pointer dereference,一系列panic堆栈,然后是:
[GIN] 2019/04/11 - 22:07:01 | 500 | 2.403482ms | 127.0.0.1 | GET /getc?field_a=hello&field_c=world,显示状态码是500。
可见,对于结构体嵌套解析,只有结构体是大写的情况下才可以有效解析,小写的情况下,要么不解析,要么解析出现异常。
下面再看一段代码,官方提示的错误:
代码4:
package main import (
"github.com/gin-gonic/gin"
) type StructA struct {
FieldA string
} type StructB struct {
NestedStruct StructA `form:"field_a"`
FieldB string `form:"field_b"`
} type StructC struct {
NestedStructPointer *StructA `form:"field_a"`
FieldC string `form:"field_c"`
} func GetDataB(c *gin.Context) {
var b StructB
c.Bind(&b)
c.JSON(200, gin.H{
"a": b.NestedStruct,
"b": b.FieldB,
})
} func GetDataC(c *gin.Context) {
var b StructC
c.Bind(&b)
c.JSON(200, gin.H{
"a": b.NestedStructPointer,
"c": b.FieldC,
})
} func main() {
r := gin.Default()
r.GET("/getb", GetDataB)
r.GET("/getc", GetDataC) r.Run()
}
这里注意StructA结构体的tag的位置发生了变化。结果如下:
curl "http://localhost:8080/getb?field_a=hello&field_b=world"
{"a":{"FieldA":""},"b":""}
curl "http://localhost:8080/getc?field_a=hello&field_c=world"
{"a":null,"c":""}
可见,这种书写tag的方式存在问题,对应的结构体成员不能正确的解析。)
关于其他情况, 经过测试
(1)对于代码1,将其中的StructA改写外structA,参数可以正确解析。
(2)对于代码1,将NestedStruct改为nestedStruct, NestedStructPointer改为nestedStructPointer,对应字段不再解析。
关于tag中的binding:"required"参数,我有一点需要补充的,下面为实例代码:
代码5:
package main import (
"github.com/gin-gonic/gin"
) type StructA struct {
FieldA int `form:"field_a" binding:"required"`
} type StructB struct {
NestedStruct StructA
FieldB string `form:"field_b" binding:"required"`
} func GetDataB(c *gin.Context) {
var b StructB
c.Bind(&b)
c.JSON(200, gin.H{
"a": b.NestedStruct,
"b": b.FieldB,
})
} func main() {
r := gin.Default()
r.GET("/getb", GetDataB) r.Run()
}
注意FieldA的类型和tag,类型由String改为int, tag添加了`bind:"required"`。测试结果如下:
curl "http://localhost:8080/getb?field_a=hello&field_b=world"
{"a":{"FieldA":0},"b":""}
服务端有一个额外的打印:
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 200
curl "http://localhost:8080/getb?field_a=0&field_b=world"
{"a":{"FieldA":0},"b":"world"}
服务端有一个额外的打印:
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 200
curl "http://localhost:8080/getb?field_b=world"
{"a":{"FieldA":0},"b":"world"}
服务端有一个额外的打印:
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 200
curl "http://localhost:8080/getb?field_a=1&field_b=world"
{"a":{"FieldA":1},"b":"world"}
服务端没有额外的打印。
curl "http://localhost:8080/getb?field_a=1&field_b="
{"a":{"FieldA":1},"b":""}
服务端有一个额外的打印:
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 200
可见,gin对于bind:"required"的判断非常简单,对于int类型,是判断这个int类型是否为0,无论是否显示设置的0,都视为参数错误,对于字符串参数来说,是判断是否为空字符串。
gin的url查询参数解析的更多相关文章
- url查询参数解析
url查询参数解析 1.获取url的各部分值 举例http://i.cnblogs.com/EditPosts.aspx?opt=1 1.window.location.href(设置或获取整个 UR ...
- Node基础:url查询参数解析之querystring
模块概述 在nodejs中,提供了querystring这个模块,用来做url查询参数的解析,使用非常简单. 模块总共有四个方法,绝大部分时,我们只会用到 .parse(). .stringify() ...
- 获取url查询参数的方法
/** * 获取url查询参数的方法 * @param name * @returns {null} * @constructor */ function GetQueryString(name) { ...
- angular6 监听url查询参数变化刷新页面
快照snapshot取到的参数是组件第一次渲染时候的参数,当我们在页面中需要根据不同的url查询参数显示不同的内容时,快照就不能满足我们的需要了,这时候就要用ActivatedRoute服务的quer ...
- 函数parseQuery用于解析url查询参数
在百度上找的,以后忘了再看. 语法如下: var obj = parseQuery(query) query是被解析的查询参数,函数返回解析后的对象. 使用范例如下: var jerry = pars ...
- URL网址参数解析类
/** * Created by myc on 2015/12/9. */ import android.text.TextUtils; import java.util.HashMap; impor ...
- react获取url查询参数
继承自React.Component的this.props.location.query对象下有当前url的各种查询参数.简单的例子:在控制台打印这个对象 import React from 'rea ...
- 将url的查询参数解析成字典对象
1, 这个题目不约而同的出现在了多家公司的面试题中,当然也是因为太过于典型,解决方案无非就是拆字符或者用正则匹配来解决,我个人强烈建议用正则匹配,因为url允许用户随意输入,如果用拆字符的方式,有任何 ...
- 一种快速构造和获取URL查询参数的方法:URLSearchParams
URLSearchParams 接口定义了一些实用的方法来处理 URL 的查询字符串. URLSearchParams()是个构造函数,将返回一个可以操作查询字符串的对象. 常用方法: 1.构造查询字 ...
随机推荐
- iOS跳转第三方应用举例一号店和京东
1.首先要跳转到第三方应用都需要知道第三方应用的scheme,虽然百度能得到很多,但是不乏一些新增的或者改了的,怎么获得APP的scheme,鉴于现在iTunes不好用了,介绍一个app ---app ...
- python--基本数据 类型
数据就是我们变量的值:python中变量保存的是内存地址 变量必须先赋值或者声明才能使用!! 1.数值型 整型 int (python3中int就是长整型,与python2中int不同,另外,pyth ...
- LoadRunner学习笔记(1)--异常处理方法
1.查看端口号占用情况 cmd -> netstat -ano 找到进程关闭后在重启网站 2.LR录制脚本时为何不弹出IE浏览器 启动浏览器,打开Internet选项对话框,切换到高级标签 ...
- [亲身实践]linux命令行下配置网路
1.在命令行下输入setup, 2.之后出现下图,选择网络配置 4.配置IP地址,子网掩码,DNS 5.保存之后回到命令行模式下,输入service network restart,至此网络配置完成
- bis.org
巴塞尔官网包含了很多文档,看起来容易晕,简单说明一下. 首先,文档有几种类型(https://www.bis.org/bcbs/help/publ_types.htm): S: Standards 最 ...
- autofac使用总结
转摘自:http://niuyi.github.io/blog/2012/04/06/autofac-by-unit-test/ 注册部分: AutoFac是.net平台下的IOC容器产品,它可以管理 ...
- UML第二次作业:类在类图中的表示
类在类图中的表示 一.概览 1.plant UML语法学习小结 2.班级学生管理系统中的 —— “学生” 类的属性.方法 3.类图脚本程序 4.类图示例 二.类图语法学习小结 1.类之间的关系 通过某 ...
- 用python给邮箱发邮件,问题,以及解决方法。
模版 import smtplib #导入相关模块 from email.mime.text import MIMEText from email.utils import formataddr de ...
- SDL播放YUV——循环
#include "SDL.h" #include "as_lesson_log.h" #define PATH_YUV420 "/sdcard/ou ...
- 上手d3js
0---什么是d3js: d3js是一个开源的,基于对svg操作的数据可视化框架,简单的说他提供了数据提供了一系列的数据可视化工具,可以用他很方便的创造出关于svg的动画:svg动画具有可伸缩,不失真 ...