对Golang中的FORM相关字段理解


Posted in Golang onMay 02, 2021

Form 字段

通过调用Request结构体提供的方法,我们可以将URL、Body、或者以上两者的数据提取到该结构体的Form、PostForm和MultipartForm等字段中。

(1)调用ParseForm方法或者ParseMultipartForm方法,对请求进行分析

(2)访问相应的字段

事例:

package main
import (
 "net/http"
 "fmt"
)
func process(w http.ResponseWriter, r *http.Request) {
 r.ParseForm()
 //ParseForm 对请求进行语法分析
 fmt.Fprintln(w,r.MultipartForm)
}
func main() {
 server := http.Server{
  Addr:"127.0.0.1:8080",
 }
 http.HandleFunc("/process",process)
 server.ListenAndServe()
}

创建一个具体表单

<!DOCTYPE html>
<html>
<head>
 <meta  http-equiv="Content-Type" content="text/html; charset=utf-8" />
 <title>GoWebPrograming</title>
</head>
<body>
 <form action="http://127.0.0.1:8080/process?hello=world&thread=get"
 method="post" enctype="application/x-www-form-urlencoded">
  <input type="text" name="hello"  value="你好 世界"/>
  <input type="text" name="post" value="456" />
  <input type="submit" />
 </form>
</body>
</html>

我们在浏览器运行html文件,结果为:

map[hello:[你好 世界 world] post:[456] thread:[get]]

我们发现这个结构是一个map,他的键为字符串,而建的值是由字符串组成的一个切片。

这个结构总是包含查询的值hello=world, thread=get,还有表单值hello=123和post=456,这些值都进行了url的解码。

比如你好世界之间有空格,说明不是编码之后的%20。

PostForm 字段

执行语句r.Form[“post”]会返回一个切片,切片里包含了表单提交的数据和url中的数据就像“你好世界”和“world” 是一组切片值。但是表单值在切片中总会排在url之前。 ( hello:[你好 世界 world] )

如果我们只想获得表单值而不是url的值,我们可以使用Request结构的PostForm字段,

我们将r.Form 改为 r.PostForm 会出现如下结果

map[hello:[你好 世界] post:[456]]

我们将 enctype="application/x-www-form-urlencoded"改为 enctype=“multipart/form-data”, 结果如下:

map[]

会得到一个空的map,这是为什么呢???

如果我们将 enctype="application/x-www-form-urlencoded"改为 enctype=“multipart/form-data”,并改回 r.Form。会出现以下结果:

map[hello:[world] thread:[get]]

这是因为ParseForm字段只支持"application/x-www-form-urlencoded"编码,所以r.Form不会反悔任何表单值,而是只返回url的查询值。

为了解决这个问题,我们需要通过MultipartForm字段来获取multipart/form-data编码的表单值。

补充:go通过http发送form-data

首先是获取form-data内容

func ResendFormFile(r *http.Request, URL string) {
 data := r.FormValue("data")
 formFile, fileHeader, err := r.FormFile("pic")
 if err != nil {
  return
 }
 _, status := RequestPost(formFile, fileHeader.Filename, []byte(data), URL)
 if (status / 100) != 2 {
  fmt.Println("转发图片失败")
 }
 return
}

然后是发送

func RequestPost(formFile multipart.File, filename string, data []byte, postURL string) (resp interface{}, status int) {
 buf := new(bytes.Buffer)
 w := multipart.NewWriter(buf)
 if fw, err := w.CreateFormField("data"); err == nil {
  fw.Write(data)
 }
 if createFormFile, err := w.CreateFormFile("pic", filename); err == nil {
  readAll, _ := ioutil.ReadAll(formFile)
  createFormFile.Write(readAll)
 }
 w.Close()
 req, err := http.NewRequest(http.MethodPost, postURL, buf)
 if err != nil {
  return
 }
 // Don't forget to set the content type, this will contain the boundary.
 req.Header.Set("Content-Type", w.FormDataContentType())
 client := &http.Client{}
 res, err := client.Do(req)
 if err != nil {
  return
 }
 return res.Body, res.StatusCode
}

这样返回的body是不可以直接json序列化的

可以先使用ioutil读出来或者byte.Buffer进行中转都是比较简单的选择

func UnmarshalWriter(body io.ReadCloser, w http.ResponseWriter) {
 all, _ := ioutil.ReadAll(body)
 buffer := bytes.NewBuffer(all)
 buffer.WriteTo(w)
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。如有错误或未考虑完全的地方,望不吝赐教。

Golang 相关文章推荐
golang 实现两个结构体复制字段
Apr 28 Golang
解决Go gorm踩过的坑
Apr 30 Golang
golang slice元素去重操作
Apr 30 Golang
go设置多个GOPATH的方式
May 05 Golang
试了下Golang实现try catch的方法
Jul 01 Golang
K8s部署发布Golang应用程序的实现方法
Jul 16 Golang
Go语言并发编程 sync.Once
Oct 16 Golang
Golang日志包的使用
Apr 20 Golang
GoFrame基于性能测试得知grpool使用场景
Jun 21 Golang
Go语言怎么使用变长参数函数
Jul 15 Golang
基于Python实现西西成语接龙小助手
Aug 05 Golang
Go gorilla/sessions库安装使用
Aug 14 Golang
解决go在函数退出后子协程的退出问题
Apr 30 #Golang
Go语言 go程释放操作(退出/销毁)
golang DNS服务器的简单实现操作
golang slice元素去重操作
Apr 30 #Golang
Golang中interface{}转为数组的操作
Apr 30 #Golang
解决Go gorm踩过的坑
Apr 30 #Golang
Golang 如何实现函数的任意类型传参
Apr 29 #Golang
You might like
PHP脚本的10个技巧(2)
2006/10/09 PHP
PHP从二维数组得到N层分类树的实现代码
2016/10/11 PHP
一个js的tab切换效果代码[代码分离]
2010/04/11 Javascript
基于jquery的表头固定的若干方法
2011/01/27 Javascript
固定表格行列(expression)在IE下适用
2013/07/25 Javascript
JS实现往下不断流动网页背景的方法
2015/02/27 Javascript
JS获取月份最后天数、最大天数与某日周数的方法
2015/12/08 Javascript
Bootstrap项目实战之首页内容介绍(全)
2016/04/25 Javascript
jQuery EasyUI Pagination实现分页的常用方法
2016/05/21 Javascript
jQuery+Ajax实现用户名重名实时检测
2017/06/01 jQuery
Angular2.js实现表单验证详解
2017/06/23 Javascript
vue自定义filters过滤器
2018/04/26 Javascript
vue利用v-for嵌套输出多层对象,分别输出到个表的方法
2018/09/07 Javascript
Nodejs核心模块之net和http的使用详解
2019/04/02 NodeJs
vue双向绑定数据限制长度的方法
2019/11/04 Javascript
axios如何取消重复无用的请求详解
2019/12/15 Javascript
Nuxt.js的路由跳转操作(页面跳转nuxt-link)
2020/11/06 Javascript
原生js实现自定义难度的扫雷游戏
2021/01/22 Javascript
[05:49]2014DOTA2TI4正赛第二日综述 昔日冠军纷纷落马 VG LGD占尽先机
2014/07/20 DOTA
[00:52]DOTA2齐天大圣预告片
2016/08/13 DOTA
Python反射的用法实例分析
2018/02/11 Python
Python使用 Beanstalkd 做异步任务处理的方法
2018/04/24 Python
python时间序列按频率生成日期的方法
2019/05/14 Python
Python叠加矩形框图层2种方法及效果
2020/06/18 Python
python文件编写好后如何实践
2020/07/07 Python
python sleep和wait对比总结
2021/02/03 Python
Algenist奥杰尼官网:微藻抗衰老护肤品牌
2017/07/15 全球购物
ALDO美国官网:加拿大女鞋品牌
2018/12/28 全球购物
二手房购房意向书范本
2014/04/01 职场文书
幼儿园中班评语大全
2014/04/17 职场文书
企业安全生产目标责任书
2014/07/23 职场文书
邹越感恩父母演讲稿
2014/08/28 职场文书
教师批评与自我批评心得体会
2014/10/16 职场文书
2014年流动人口工作总结
2014/11/26 职场文书
2015个人年度工作总结范文
2015/05/28 职场文书
幼儿园中班教育随笔
2015/08/14 职场文书