对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语言操作数据库及其常规操作的示例代码
Apr 21 Golang
Go缓冲channel和非缓冲channel的区别说明
Apr 25 Golang
goland 清除所有的默认设置操作
Apr 28 Golang
golang 生成对应的数据表struct定义操作
Apr 28 Golang
Golang 空map和未初始化map的注意事项说明
Apr 29 Golang
golang 接口嵌套实现复用的操作
Apr 29 Golang
go语言中GOPATH GOROOT的作用和设置方式
May 05 Golang
golang中的并发和并行
May 08 Golang
入门学习Go的基本语法
Jul 07 Golang
浅谈GO中的Channel以及死锁的造成
Mar 18 Golang
Golang 字符串的常见操作
Apr 19 Golang
Golang MatrixOne使用介绍和汇编语法
Apr 19 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
《魔兽世界》惊魂幻象将获得调整
2020/03/08 其他游戏
gd库图片下载类实现下载网页所有图片的php代码
2012/08/20 PHP
PHP自定义多进制的方法
2016/11/03 PHP
JObj预览一个JS的框架
2008/03/13 Javascript
利用jQuery的$.event.fix函数统一浏览器event事件处理
2009/12/21 Javascript
jquery获取input的value问题说明
2010/08/19 Javascript
javascript 正则表达式相关应介绍
2012/11/27 Javascript
GRID拖拽行的实例代码
2013/07/18 Javascript
JS拖动鼠标画出方框实现鼠标选区的方法
2015/08/05 Javascript
JS动态日期时间的获取方法
2015/09/28 Javascript
angular.js之路由的选择方法
2016/09/24 Javascript
JQuery Dialog对话框 不能通过Esc关闭的原因分析及解决办法
2017/01/18 Javascript
js HTML5 canvas绘制图片的方法
2017/09/08 Javascript
jQuery Datatables表头不对齐的解决办法
2017/11/27 jQuery
express+mockjs实现模拟后台数据发送功能
2018/01/07 Javascript
angular实现页面打印局部功能的思考与方法
2018/04/13 Javascript
[01:09]DOTA2次级职业联赛 - 99战队宣传片
2014/12/01 DOTA
详解Python3的TFTP文件传输
2018/06/26 Python
python+splinter自动刷新抢票功能
2018/09/25 Python
python读取TXT每行,并存到LIST中的方法
2018/10/26 Python
Python从数据库读取大量数据批量写入文件的方法
2018/12/10 Python
Python判断是否json是否包含一个key的方法
2018/12/31 Python
python添加模块搜索路径和包的导入方法
2019/01/19 Python
python3下载抖音视频的完整代码
2019/06/05 Python
Mac 使用python3的matplot画图不显示的解决
2019/11/23 Python
详解python 破解网站反爬虫的两种简单方法
2020/02/09 Python
python使用gdal对shp读取,新建和更新的实例
2020/03/10 Python
FitFlop美国官网:英国符合人体工学的鞋类品牌
2018/10/05 全球购物
如何在C# winform中异步调用web services
2015/09/21 面试题
护士上岗前培训自我鉴定
2014/04/20 职场文书
美食节策划方案
2014/05/26 职场文书
协议书范文
2015/01/27 职场文书
2019年入党思想汇报格式与要求
2019/06/25 职场文书
python实现自动化群控的步骤
2021/04/11 Python
python实现会员管理系统
2022/03/18 Python
Python保存并浏览用户的历史记录
2022/04/29 Python