对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 相关文章推荐
go语言中切片与内存复制 memcpy 的实现操作
Apr 27 Golang
Golang 使用Map实现去重与set的功能操作
Apr 29 Golang
解决Golang time.Parse和time.Format的时区问题
Apr 29 Golang
解决golang结构体tag编译错误的问题
May 02 Golang
golang 定时任务方面time.Sleep和time.Tick的优劣对比分析
May 05 Golang
Golang 获取文件md5校验的方法以及效率对比
May 08 Golang
Golang实现AES对称加密的过程详解
May 20 Golang
go web 预防跨站脚本的实现方式
Jun 11 Golang
深入理解go缓存库freecache的使用
Feb 15 Golang
Go语言 详解net的tcp服务
Apr 14 Golang
Golang实现可重入锁的示例代码
May 25 Golang
Go gorilla securecookie库的安装使用详解
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正则校验用户名介绍
2008/07/19 PHP
php和数据库结合的一个简单的web实例 代码分析 (php初学者)
2011/07/28 PHP
如何批量替换相对地址为绝对地址(利用bat批处理实现)
2013/05/27 PHP
destoon公司主页模板风格的添加方法
2014/06/20 PHP
php实现以只读方式打开文件的方法
2015/03/16 PHP
PHP实现简单数字分页效果
2015/07/26 PHP
两种WEB下的模态对话框 (asp.net或js的分别实现)
2009/12/02 Javascript
获取客户端网卡MAC地址和IP地址实现JS代码
2013/03/17 Javascript
Jquery post传递数组方法实现思路及代码
2013/04/28 Javascript
jquery点击页面任何区域实现鼠标焦点十字效果
2013/06/21 Javascript
js如何设置在iframe框架中指定div不显示
2013/12/04 Javascript
Jquery实现由下向上展开效果的例子
2014/12/08 Javascript
JavaScript通过prototype给对象定义属性用法实例
2015/03/23 Javascript
Javascript之Number对象介绍
2016/06/07 Javascript
浅谈jquery高级方法描述与应用
2016/10/04 Javascript
如何提高数据访问速度
2016/12/26 Javascript
Javascript ES6中对象类型Sets的介绍与使用详解
2017/07/17 Javascript
JS实现的缓冲运动效果示例
2018/04/30 Javascript
解决jquery validate 验证不通过后验证正确的信息仍残留在label上的方法
2019/08/27 jQuery
[03:59]第二届DOTA2亚洲邀请赛选手传记-VGJ.rOtk
2017/04/03 DOTA
python相似模块用例
2016/03/04 Python
Python实现识别手写数字 简易图片存储管理系统
2018/01/29 Python
python实现log日志的示例代码
2018/04/28 Python
Python实现的简单计算器功能详解
2018/08/25 Python
Pandas过滤dataframe中包含特定字符串的数据方法
2018/11/07 Python
python通过TimedRotatingFileHandler按时间切割日志
2019/07/17 Python
使用python代码进行身份证号校验的实现示例
2019/11/21 Python
简述进程的启动、终止的方式以及如何进行进程的查看
2014/02/20 面试题
大学生入党思想汇报
2014/01/01 职场文书
建筑工程毕业生自我鉴定
2014/01/14 职场文书
餐饮总经理岗位职责
2014/03/07 职场文书
培训班开班仪式主持词
2014/03/28 职场文书
酒店销售经理岗位职责
2015/04/02 职场文书
2015年房地产销售工作总结
2015/04/20 职场文书
2015入党个人自传范文
2015/06/26 职场文书
初中思品教学反思
2016/02/20 职场文书