对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 相关文章推荐
goland 恢复已更改文件的操作
Apr 28 Golang
go语言中json数据的读取和写出操作
Apr 28 Golang
golang 实现两个结构体复制字段
Apr 28 Golang
基于Go Int转string几种方式性能测试
Apr 28 Golang
Go 实现英尺和米的简单单位换算方式
Apr 29 Golang
解决goland 导入项目后import里的包报红问题
May 06 Golang
Golang全局变量加锁的问题解决
May 08 Golang
浅谈Golang 切片(slice)扩容机制的原理
Jun 09 Golang
试了下Golang实现try catch的方法
Jul 01 Golang
Go语言编译原理之源码调试
Aug 05 Golang
go goth封装第三方认证库示例详解
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/06/20 PHP
php实现分页工具类分享
2014/01/09 PHP
php网页版聊天软件实现代码
2016/08/12 PHP
yii2实现 &quot;上一篇,下一篇&quot; 功能的代码实例
2017/02/04 PHP
兼容Mozilla必须知道的知识。
2007/01/09 Javascript
漂亮的提示信息(带箭头)
2007/03/21 Javascript
javascript 兼容FF的onmouseenter和onmouseleave的代码
2008/07/19 Javascript
理解JavaScript变量作用域更轻松
2009/10/25 Javascript
Jquery 扩展方法
2010/05/06 Javascript
Ajax 数据请求的简单分析
2011/04/05 Javascript
JavaScript将Table导出到Excel实现思路及代码
2013/03/13 Javascript
用js实现控件的隐藏及style.visibility的使用
2013/06/14 Javascript
javascript实现动态改变层大小的方法
2015/05/14 Javascript
JS组件Bootstrap导航条使用方法详解
2016/04/29 Javascript
详解JavaScript中return的用法
2017/05/08 Javascript
基于webpack 实用配置方法总结
2017/09/28 Javascript
nodejs实现爬取网站图片功能
2017/12/14 NodeJs
Vue中图片Src使用变量的方法
2019/10/30 Javascript
js抽奖转盘实现方法分析
2020/05/16 Javascript
Vue项目配置跨域访问和代理proxy设置方式
2020/09/08 Javascript
使用Python下载歌词并嵌入歌曲文件中的实现代码
2015/11/13 Python
Python实现的生产者、消费者问题完整实例
2018/05/30 Python
在python中使用requests 模拟浏览器发送请求数据的方法
2018/12/26 Python
matplotlib自定义鼠标光标坐标格式的实现
2021/01/08 Python
HTML5重塑Web世界它将如何改变互联网
2012/12/17 HTML / CSS
露营世界:Camping World
2017/02/02 全球购物
波兰最大的电商平台:Allegro.pl
2021/02/06 全球购物
SQL注入攻击的种类有哪些
2013/12/30 面试题
数控技校生自我鉴定
2014/04/19 职场文书
安全生产先进个人总结
2015/02/15 职场文书
2016年质量月活动总结报告
2016/04/05 职场文书
标准发言稿结尾
2019/07/18 职场文书
pytorch 实现在测试的时候启用dropout
2021/05/27 Python
MongoDB安装使用并实现Python操作数据库
2021/06/28 MongoDB
Go语言的协程上下文的几个方法和用法
2022/04/11 Golang
JS前端使用canvas实现物体的点选示例
2022/08/05 Javascript