再也不怕获取不到Gin请求参数了

再也不怕获取不到Gin请求参数了,第1张

以前阅读过Gin源码、并仿照Gin自己写了一个简单版的框架。

Gin框架简洁版Gin源码剖析

最近在使用的时候,发现前端调用传递参数方式各异,各种稀奇古怪的方式都会用到。这篇文章主要盘一下如何获取到参数,方便今后使用。

代码位置:https://github.com/shidawuhen/asap/tree/master/controller/paramtype

1.类型

HTTP请求方法有很多[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们常用的是GET和POST,本次主要讲GET和POST,差不多可以覆盖所有的传递参数方式了。使用POSTMAN,可以方便的看到传递参数方式。

1.1GET

共一种,这种方式称呼为Query方式

1.2POST

共四种,分别为form-data、x-www-form-urlencoded、raw、binary,第五种和GET一样,不计算在内

2.实践 2.1 GET 2.1.1 Query

query支持的函数很多,Param函数需要说一下,其使用需要在router上配置

代码
func paramTypeFunc(router *gin.Engine) {
   router.GET("/paramtype/query/:param", paramtype.Query)
}
/**
@date: 2021/5/24
**/
package paramtype

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
)

/**
 * @Description: GET Query参数获取实例
 * @param c
 */
func Query(c *gin.Context) {
	//需定义合规结构体
	rawQuery := &RawQuery{}
	c.ShouldBindQuery(rawQuery)
	fmt.Printf("%+v \n", rawQuery)

	param := c.Param("param")
	fmt.Println(param)

	query := c.Query("query")
	fmt.Println(query)

	defaultQuery := c.DefaultQuery("defaultQuery", "no")
	fmt.Println(defaultQuery)

	getQuery, res := c.GetQuery("getQuery")
	fmt.Println(getQuery, res)

	queryArray := c.QueryArray("queryArray")
	fmt.Println(queryArray)

	getQueryArray, res := c.GetQueryArray("getQueryArray")
	fmt.Println(getQueryArray, res)

	queryMap := c.QueryMap("queryMap")
	fmt.Println(queryMap)

	getQueryMap, res := c.GetQueryMap("getQueryMap")
	fmt.Println(getQueryMap)

	c.String(http.StatusOK, "ok")
}
调用

CODE: GET /paramtype/query/this is param?query=this is query&defaultQuery=this is defaultQuery&getQuery=this is getQuery&queryArray=this&queryArray=is&queryArray=queryArray&getQueryArray=this&getQueryArray=is&getQueryArray=getQueryArray&queryMap[1]=this&queryMap[2]=is&queryMap[3]=queryMap&getQueryMap[1]=this&getQueryMap[2]=is&getQueryMap[3]=getQueryMap

HTTP/1.1

Host: 127.0.0.1:8082

Content-Type: application/x-www-form-urlencoded

Cache-Control: no-cache

Postman-Token: e0fdeb2e-78c2-c26d-03ad-a4a6715b3d66

输出

&{Query:this is query}

this is param

this is query

this is defaultQuery

this is getQuery true

[this is queryArray]

[this is getQueryArray] true

map[1:this 2:is 3:queryMap]

map[1:this 2:is 3:getQueryMap]

2.2 POST 2.2.1 form-data

form-data的获取正规正矩。 form-data就是http请求中的multipart/form-data,它会将表单的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件。当上传的字段是文件时,会有Content-Type来说明文件类型;content-disposition,用来说明字段的一些信息;

如果是文件,可以通过FormFile或者MultipartForm获取文件内容,FormFile获取一个,MultipartForm获取多个。使用SaveUploadedFile存储文件。

代码
/**
@date: 2021/5/25
**/
package paramtype

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
)

type PostFormStruct struct {
	GetPostForm string `json:"getPostForm" uri:"getPostForm" form:"getPostForm"`
}

/**
 * @Author: POST form数据获取
 * @Description:
 * @param c
 */
func PostFormData(c *gin.Context) {
	//需定义合规结构体
	postFormStruct := &PostFormStruct{}
	c.ShouldBind(postFormStruct)
	fmt.Printf("%+v \n", postFormStruct)

	postForm := c.PostForm("postForm")
	fmt.Println(postForm)

	defaultPostForm := c.DefaultPostForm("defaultPostForm", "no")
	fmt.Println(defaultPostForm)

	getPostForm, res := c.GetPostForm("getPostForm")
	fmt.Println(getPostForm, res)

	postFormArray := c.PostFormArray("postFormArray")
	fmt.Println(postFormArray)

	getPostFormArray, res := c.GetPostFormArray("getPostFormArray")
	fmt.Println(getPostFormArray, res)

	postFormMap := c.PostFormMap("postFormMap")
	fmt.Println(postFormMap)

	getPostFormMap, res := c.GetPostFormMap("getPostFormMap")
	fmt.Println(getPostFormMap)

	c.String(http.StatusOK, "ok")
}
调用

CODE: POST /paramtype/postformdata HTTP/1.1

Host: 127.0.0.1:8082

Cache-Control: no-cache

Postman-Token: 83c078e3-b7de-d154-dda1-477cc4f2f450

Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

------WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name=“postForm”

this is postForm

------WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name=“defaultPostForm”

this is defaultPostForm

------WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name=“getPostForm”

this is getPostForm

------WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name=“postFormArray”

this

------WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name=“postFormArray”

is

------WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name=“postFormArray”

postFormArray

------WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name=“getPostFormArray”

this

------WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name=“getPostFormArray”

is

------WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name=“getPostFormArray”

getPostFormArray

------WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name=“postFormMap[1]”

this

------WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name=“postFormMap[2]”

is

------WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name=“postFormMap[3]”

postFormMap

------WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name=“getPostFormMap[1]”

this

------WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name=“getPostFormMap[2]”

is
------WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name=“getPostFormMap[3]”

getPostFormMap

------WebKitFormBoundary7MA4YWxkTrZu0gW–

输出

&{GetPostForm:this is getPostForm}

this is postForm

this is defaultPostForm

this is getPostForm true

[this is postFormArray]

[this is getPostFormArray] true

map[1:this 2:is 3:postFormMap]

map[1:this 2:is 3:getPostFormMap]

2.2.2 x-www-form-urlencoded

x-www-form-urlencoded是application/x-www-from-urlencoded,将表单内的数据转换为键值对,&分隔。

当form表单的action为get时,浏览器用x-www-form-urlencoded的编码方式,将表单数据编码为
(name1=value1&name2=value2…),然后把这个字符串append到url后面,用?分隔,跳转到这个新的url。

当form表单的action为post时,浏览器将form数据封装到http body中,然后发到server。该格式不能提交文件。

代码

同form-data

调用

CODE: POST /paramtype/postformdata HTTP/1.1

Host: 127.0.0.1:8082

Content-Type: application/x-www-form-urlencoded

Cache-Control: no-cache

Postman-Token: 62ffa49a-e61f-0277-db62-dd9c727e182d

postForm=this+is+postForm&defaultPostForm=this+is+defaultPostForm&getPostForm=this+is+getPostForm&postFormArray=this&postFormArray=is&postFormArray=postFormArray&getPostFormArray=this&getPostFormArray=is&getPostFormArray=getPostFormArray&postFormMap%5B1%5D=this&postFormMap%5B2%5D=is&postFormMap%5B3%5D=postFormMap&getPostFormMap%5B1%5D=this&getPostFormMap%5B2%5D=is&getPostFormMap%5B3%5D=getPostFormMap

输出

同form-data

2.2.3 raw

可以上传任意格式的文本,包括text、json、xml、html等。

raw一般使用Bind和ShouldBind系列函数来获取数据,两者的区别是如果输入数据无效,Bind会将返回状态设置为400,并且中断,ShouldBind就没有这么狠。Bind和ShouldBind根据Content-Type来判断是json/xml/yaml格式,做对应解析。

ShouldBindUri和ShouldBindQuery使用起来有些技巧,代码中对此有标注。

代码
router.POST("/paramtype/raw/:name", paramtype.Raw)
/**
@date: 2021/5/26
**/
package paramtype

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
)

type RawStruct struct {
	Id   string
	Text string
}

type RawUri struct {
	Name string `json:"name" uri:"name"`
}

type RawQuery struct {
	Query string `json:"query" uri:"query" form:"query"`
}

/**
 * @Description: POST Raw数据获取
 * @param c
 */
func Raw(c *gin.Context) {

	raw := &RawStruct{}
	c.ShouldBind(raw)
	fmt.Printf("%+v \n", raw)

	//需定义合规结构体
	rawUri := &RawUri{}
	c.ShouldBindUri(rawUri)
	fmt.Printf("%+v \n", rawUri)

	//需定义合规结构体
	rawQuery := &RawQuery{}
	c.ShouldBindQuery(rawQuery)
	fmt.Printf("%+v \n", rawQuery)

	c.String(http.StatusOK, "ok")
}
调用

CODE:

POST /paramtype/raw/I am raw name?query=I am query HTTP/1.1

Host: 127.0.0.1:8082

Content-Type: application/json

Cache-Control: no-cache

Postman-Token: 1c7f46a5-2ea2-36ac-1f9b-29dab2a90d62

{“id”:“1”,“text”:“I am raw json”}

输出

&{Id:1 Text:I am raw json}

&{Name:I am raw name}

&{Query:I am query}

2.2.4 binary

相当于Content-Type:application/octet-stream,从字面意思得知,只可以上传二进制数据,通常用来上传文件,由于没有键值,所以,一次只能上传一个文件。

Gin中没有找到相关的函数,文件上传使用的是multipart/form-data,如果大家有相关资料的话,可以告知我一下。

3.请求参数

参数

GET:
query:this is query
defaultQuery:this is defaultQuery
getQuery:this is getQuery
queryArray:this
queryArray:is
queryArray:queryArray
getQueryArray:this
getQueryArray:is
getQueryArray:getQueryArray
queryMap[1]:this
queryMap[2]:is
queryMap[3]:queryMap
getQueryMap[1]:this
getQueryMap[2]:is
getQueryMap[3]:getQueryMap
POST:
postForm:this is postForm
defaultPostForm:this is defaultPostForm
getPostForm:this is getPostForm
postFormArray:this
postFormArray:is
postFormArray:postFormArray
getPostFormArray:this
getPostFormArray:is
getPostFormArray:getPostFormArray
postFormMap[1]:this
postFormMap[2]:is
postFormMap[3]:postFormMap
getPostFormMap[1]:this
getPostFormMap[2]:is
getPostFormMap[3]:getPostFormMap
总结

Gin获取输入数据还是挺复杂的,这里简单总结一下:

Get的使用Query、Param系列Post的form-data和x-www-form-urlencoded使用PostForm系列Get和Post的数据都可以用Bind、ShouldBind系列,不过结构体的tag需要写正确文件上传使用form-data,通过函数FormFile或者MultipartForm 资料

https://geektutu.com/post/quick-go-gin.html Go Gin 简明教程

https://github.com/gin-gonic/gin 源码

https://gin-gonic.com/zh-cn/docs/ 中文文档

https://www.kancloud.cn/shuangdeyu/gin_book/949436 gin中文文档

https://www.kancloud.cn/adapa/gingolang/1124990 Gin框架入门到入土

gin-安装,修改启动端口,get/post 请求参数,模型绑定shouldbind,自定义验证器/表单验证

一文搞懂gin各种上传文件

postman中 form-data、x-www-form-urlencoded、raw、binary的区别

最后

大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)

我的个人博客为:https://shidawuhen.github.io/

往期文章回顾:

招聘

字节跳动|内推大放送字节跳动|今日头条广州服务端研发工程师内推字节跳动|抖音电商急招上海前端开发工程字节跳动|抖音电商上海资深服务端开发工程师-交易字节跳动|抖音电商武汉服务端(高级)开发工程师字节跳动|飞书大客户产品经理内推咯字节跳动|抖音电商服务端技术岗位虚位以待字节跳动招聘专题

设计模式

Go设计模式(12)-桥接模式Go设计模式(11)-代理模式Go设计模式(10)-原型模式Go设计模式(9)-建造者模式Go设计模式(8)-抽象工厂Go设计模式(7)-工厂模式Go设计模式(6)-单例模式Go设计模式(5)-类图符号表示法Go设计模式(4)-代码编写优化Go设计模式(4)-代码编写Go设计模式(3)-设计原则Go设计模式(2)-面向对象分析与设计Go设计模式(1)-语法

语言

一文搞懂pprofGo工具之generateGo单例实现方案Go通道实现原理Go定时器实现原理Beego框架使用Golang源码BUG追查Gin框架简洁版Gin源码剖析

架构

分页复选设计的坑支付接入常规问题限流实现2秒杀系统分布式系统与一致性协议微服务之服务框架和注册中心浅谈微服务限流实现1CDN请求过程详解常用缓存技巧如何高效对接第三方支付算法总结

存储

MySQL开发规范Redis实现分布式锁事务原子性、一致性、持久性的实现原理InnoDB锁与事务简析

网络

HTTP2.0基础教程HTTPS配置实战HTTPS连接过程TCP性能优化

工具

GoLand实用技巧根据mysql表自动生成go structMarkdown编辑器推荐-typora

读书笔记

《毛选》推荐原则资治通鉴敏捷革命如何锻炼自己的记忆力简单的逻辑学-读后感热风-读后感论语-读后感孙子兵法-读后感

思考

为动员一切力量争取胜利而斗争反对自由主义实践论评价自己的标准服务端团队假期值班方案项目流程管理对项目管理的一些看法对产品经理的一些思考关于程序员职业发展的思考关于代码review的思考

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/996110.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存