对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中切片copy复制和等号复制的区别介绍
Apr 27 Golang
Go语言切片前或中间插入项与内置copy()函数详解
Apr 27 Golang
golang 实现对Map进行键值自定义排序
Apr 28 Golang
go语言中GOPATH GOROOT的作用和设置方式
May 05 Golang
golang gopm get -g -v 无法获取第三方库的解决方案
May 05 Golang
golang 实现时间戳和时间的转化
May 07 Golang
Golang 语言控制并发 Goroutine的方法
Jun 30 Golang
victoriaMetrics库布隆过滤器初始化及使用详解
Apr 05 Golang
Golang 遍历二叉树
Apr 19 Golang
Golang解析JSON对象
Apr 30 Golang
Go gRPC进阶教程gRPC转换HTTP
Jun 16 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逐行输出(ob_flush与flush的组合)
2012/02/04 PHP
PHP防止表单重复提交的几种常用方法汇总
2014/08/19 PHP
php中有关合并某一字段键值相同的数组合并的改进
2015/03/10 PHP
注意!PHP 7中不要做的10件事
2016/09/18 PHP
学习jquery必备 api中英文对照的chm手册 下载
2007/05/03 Javascript
JS 强制设为首页的代码
2009/01/31 Javascript
百度留言本js 大家可以参考下
2009/10/13 Javascript
javascript forEach通用循环遍历方法
2010/10/11 Javascript
基于Jquery的淡入淡出的特效基础练习
2010/12/13 Javascript
超酷的网页音乐播放器DewPlayer使用方法
2010/12/18 Javascript
ExtJs中gridpanel分组后组名排序实例代码
2013/12/02 Javascript
javascript将url中的参数加密解密代码
2014/11/17 Javascript
JS绘制生成花瓣效果的方法
2015/08/05 Javascript
基于Vue如何封装分页组件
2016/12/16 Javascript
Vue子组件向父组件通信与父组件调用子组件中的方法
2018/06/22 Javascript
vue element table 表格请求后台排序的方法
2018/09/28 Javascript
jQuery与原生JavaScript选择HTML元素集合用法对比分析
2019/11/26 jQuery
vue-router的hooks用法详解
2020/06/08 Javascript
JavaScript编码小技巧分享
2020/09/17 Javascript
深入理解Python装饰器
2016/07/27 Python
tensorflow实现KNN识别MNIST
2018/03/12 Python
使用urllib库的urlretrieve()方法下载网络文件到本地的方法
2018/12/19 Python
PyQt5的PyQtGraph实践系列3之实时数据更新绘制图形
2019/05/13 Python
在windows下使用python进行串口通讯的方法
2019/07/02 Python
Python3+Appium实现多台移动设备操作的方法
2019/07/05 Python
自定义Django默认的sitemap站点地图样式
2020/03/04 Python
python多进程使用函数封装实例
2020/05/02 Python
CSS3制作文字半透明倒影效果的两种实现方式
2014/08/08 HTML / CSS
HTML5头部标签的一些常用信息小结
2016/10/23 HTML / CSS
印度尼西亚最好的小工具在线商店:Erafone.com
2019/03/26 全球购物
Delphi工程师笔试题
2013/09/21 面试题
课程设计心得体会
2013/12/28 职场文书
运动会铅球比赛加油稿
2014/09/26 职场文书
2015年纪念“卢沟桥事变”78周年活动方案
2015/05/06 职场文书
2015年国庆节演讲稿范文
2015/07/30 职场文书
windows server2016安装oracle 11g的图文教程
2022/07/15 Servers