对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缓冲channel和非缓冲channel的区别说明
Apr 25 Golang
golang在GRPC中设置client的超时时间
Apr 27 Golang
go 原生http web 服务跨域restful api的写法介绍
Apr 27 Golang
Go使用协程交替打印字符
Apr 29 Golang
go设置多个GOPATH的方式
May 05 Golang
golang 实现并发求和
May 08 Golang
浅谈Go语言多态的实现与interface使用
Jun 16 Golang
详解Go语言Slice作为函数参数的使用
Jul 02 Golang
基于Go语言构建RESTful API服务
Jul 25 Golang
Go语言实现一个简单的并发聊天室的项目实战
Mar 18 Golang
victoriaMetrics库布隆过滤器初始化及使用详解
Apr 05 Golang
golang的文件创建及读写操作
Apr 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单一接口的实现方法
2015/06/20 PHP
php创建多级目录与级联删除文件的方法示例
2019/09/12 PHP
强制设为首页代码
2006/06/19 Javascript
JavaScript DOM学习第六章 表单实例
2010/02/19 Javascript
浅谈Javascript中的Function与Object
2015/01/26 Javascript
jQuery和AngularJS的区别浅析
2015/01/29 Javascript
纯js代码制作的网页时钟特效【附实例】
2016/03/30 Javascript
JavaScript开发Chrome浏览器扩展程序UI的教程
2016/05/16 Javascript
js模糊查询实例分享
2016/12/26 Javascript
JavaScript中英文字符长度统计方法示例【按照中文占2个字符】
2017/01/17 Javascript
微信小程序富文本渲染引擎的详解
2017/09/30 Javascript
jQuery封装animate.css的实例
2018/01/04 jQuery
vue 组件中使用 transition 和 transition-group实现过渡动画
2019/07/09 Javascript
深入分析jQuery.one() 函数
2020/06/03 jQuery
js瀑布流布局的实现
2020/06/28 Javascript
vue-cli+webpack项目打包到服务器后,ttf字体找不到的解决操作
2020/08/28 Javascript
Vue 列表页带参数进详情页的操作(router-link)
2020/11/13 Javascript
win10系统中安装scrapy-1.1
2016/07/03 Python
浅谈Python 对象内存占用
2016/07/15 Python
Python Xml文件添加字节属性的方法
2018/03/31 Python
pytorch cnn 识别手写的字实现自建图片数据
2018/05/20 Python
python使用mitmproxy抓取浏览器请求的方法
2019/07/02 Python
Django项目使用CircleCI的方法示例
2019/07/14 Python
关于python pycharm中输出的内容不全的解决办法
2020/01/10 Python
Python之京东商品秒杀的实现示例
2021/01/06 Python
Django与AJAX实现网页动态数据显示的示例代码
2021/02/24 Python
Rag & Bone官网:瑞格布恩高级成衣
2018/04/19 全球购物
Snapfish爱尔兰:在线照片打印和个性化照片礼品
2018/09/17 全球购物
如何用Python输出一个Fibonacci数列
2016/08/28 面试题
社区七一党员活动方案
2014/01/25 职场文书
保证书格式范文
2014/04/28 职场文书
党员教师群众路线思想汇报范文
2014/10/28 职场文书
结婚喜宴迎宾词
2015/08/10 职场文书
2016公务员年度考核评语
2015/12/01 职场文书
一道JS算法面试题——冒泡、选择排序
2021/04/21 Javascript
html中两种获取标签内的值的方法
2022/06/16 jQuery