以前阅读过Gin源码、并仿照Gin自己写了一个简单版的框架。
最近在使用的时候,发现前端调用传递参数方式各异,各种稀奇古怪的方式都会用到。这篇文章主要盘一下如何获取到参数,方便今后使用。
代码位置:https://github.com/shidawuhen/asap/tree/master/controller/paramtype
HTTP请求方法有很多[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
我们常用的是GET和POST,本次主要讲GET和POST,差不多可以覆盖所有的传递参数方式了。使用POSTMAN,可以方便的看到传递参数方式。
共四种,分别为form-data、x-www-form-urlencoded、raw、binary,第五种和GET一样,不计算在内
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]
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]
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
可以上传任意格式的文本,包括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}
相当于Content-Type:application/octet-stream,从字面意思得知,只可以上传二进制数据,通常用来上传文件,由于没有键值,所以,一次只能上传一个文件。
Gin中没有找到相关的函数,文件上传使用的是multipart/form-data,如果大家有相关资料的话,可以告知我一下。
参数
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获取输入数据还是挺复杂的,这里简单总结一下:
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/
往期文章回顾:
招聘
设计模式
语言
架构
存储
网络
工具
读书笔记
思考