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

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

  1. Gin框架简洁版
  2. Gin源码剖析

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

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

1.类型

HTTP请求方法有很多[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
再也不怕获取不到Gin请求参数了_第1张图片

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

1.1GET

共一种,这种方式称呼为Query方式
再也不怕获取不到Gin请求参数了_第2张图片

1.2POST

共四种,分别为form-data、x-www-form-urlencoded、raw、binary,第五种和GET一样,不计算在内
再也不怕获取不到Gin请求参数了_第3张图片

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")
}
调用

再也不怕获取不到Gin请求参数了_第4张图片

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")
}
调用

再也不怕获取不到Gin请求参数了_第5张图片

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

调用

再也不怕获取不到Gin请求参数了_第6张图片

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")
}
调用

再也不怕获取不到Gin请求参数了_第7张图片

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获取输入数据还是挺复杂的,这里简单总结一下:

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

资料

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

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

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

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

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

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

  7. 一文搞懂gin各种上传文件

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

最后

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

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

往期文章回顾:

招聘

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

设计模式

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

语言

  1. 一文搞懂pprof
  2. Go工具之generate
  3. Go单例实现方案
  4. Go通道实现原理
  5. Go定时器实现原理
  6. Beego框架使用
  7. Golang源码BUG追查
  8. Gin框架简洁版
  9. Gin源码剖析

架构

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

存储

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

网络

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

工具

  1. GoLand实用技巧
  2. 根据mysql表自动生成go struct
  3. Markdown编辑器推荐-typora

读书笔记

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

思考

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

你可能感兴趣的:(语言,golang)