对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 08 Golang
goland 清除所有的默认设置操作
Apr 28 Golang
Golang 空map和未初始化map的注意事项说明
Apr 29 Golang
完美解决golang go get私有仓库的问题
May 05 Golang
go mod 安装依赖 unkown revision问题的解决方案
May 06 Golang
Golang全局变量加锁的问题解决
May 08 Golang
Go语言的协程上下文的几个方法和用法
Apr 11 Golang
在ubuntu下安装go开发环境的全过程
Aug 05 Golang
Go语言编译原理之变量捕获
Aug 05 Golang
Go gorilla securecookie库的安装使用详解
Aug 14 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变量的定义、可变变量、变量引用、销毁方法
2013/12/20 PHP
PHP正则替换函数preg_replace和preg_replace_callback使用总结
2014/09/22 PHP
PHP使用星号隐藏用户名,手机和邮箱的实现方法
2016/09/22 PHP
PHP实现单条sql执行多个数据的insert语句方法
2019/10/11 PHP
CSS+JS构建的图片查看器
2006/07/22 Javascript
JS中的substring和substr函数的区别说明
2013/05/07 Javascript
js控制web打印(局部打印)方法整理
2013/05/29 Javascript
基于HTML+CSS,jQuery编写的简易计算器后续(添加了键盘监听)
2016/01/05 Javascript
文件上传插件SWFUpload的使用指南
2016/11/29 Javascript
JavaScript 最佳实践:帮你提升代码质量
2016/12/03 Javascript
Bootstrap弹出框之自定义悬停框标题、内容和样式示例代码
2017/07/11 Javascript
BootStrap模态框和select2合用时input无法获取焦点的解决方法
2017/09/01 Javascript
基于Vue框架vux组件库实现上拉刷新功能
2017/11/28 Javascript
浅谈手写node可读流之流动模式
2018/06/01 Javascript
JS动态图片的实现方法完整示例
2020/01/13 Javascript
在NodeJs中使用node-schedule增加定时器任务的方法
2020/06/08 NodeJs
JavaScript实现多文件下载方法解析
2020/08/07 Javascript
前端使用crypto.js进行加密的函数代码
2020/08/16 Javascript
JavaScript 几种循环方式以及模块化的总结
2020/09/03 Javascript
[50:02]完美世界DOTA2联赛循环赛 Magma vs IO BO2第一场 11.01
2020/11/02 DOTA
Python、Javascript中的闭包比较
2015/02/04 Python
对python中的装包与解包实例详解
2019/08/24 Python
在Django中实现添加user到group并查看
2019/11/18 Python
python 实现人和电脑猜拳的示例代码
2020/03/02 Python
Django-silk性能测试工具安装及使用解析
2020/11/28 Python
Html5实现单张、多张图片上传功能
2019/04/28 HTML / CSS
Europcar意大利:汽车租赁
2019/07/07 全球购物
会计专业的自荐信
2013/12/12 职场文书
员工生日活动方案
2014/08/24 职场文书
县委班子四风对照检查材料思想汇报
2014/09/29 职场文书
捐资助学感谢信
2015/01/21 职场文书
本溪水洞导游词
2015/02/11 职场文书
新郎新娘致辞
2015/07/31 职场文书
2016国庆促销广告语
2016/01/28 职场文书
小学三年级数学教学反思
2016/02/16 职场文书
Python中threading库实现线程锁与释放锁
2021/05/17 Python