对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 Gin实现文件上传下载的示例代码
Apr 02 Golang
为什么不建议在go项目中使用init()
Apr 12 Golang
解决Golang中ResponseWriter的一个坑
Apr 27 Golang
解决golang在import自己的包报错的问题
Apr 29 Golang
解决Go gorm踩过的坑
Apr 30 Golang
golang fmt格式“占位符”的实例用法详解
Jul 04 Golang
使用GO语言实现Mysql数据库CURD的简单示例
Aug 07 Golang
深入理解go缓存库freecache的使用
Feb 15 Golang
如何解决goland,idea全局搜索快捷键失效问题
Apr 03 Golang
Golang数据类型和相互转换
Apr 12 Golang
Go Grpc Gateway兼容HTTP协议文档自动生成网关
Jun 16 Golang
基于Python实现西西成语接龙小助手
Aug 05 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/08/05 PHP
PHP Mysql编程之高级技巧
2008/08/27 PHP
解决php表单重复提交实现方法
2015/09/29 PHP
WordPress中获取页面链接和标题的相关PHP函数用法解析
2015/12/17 PHP
PHP在线调试执行的实现方法(附demo源码)
2016/04/28 PHP
Javascript 文件夹选择框的两种解决方案
2009/07/01 Javascript
javascript整除实现代码
2010/11/23 Javascript
超酷的网页音乐播放器DewPlayer使用方法
2010/12/18 Javascript
Node.js开发指南中的简单实例(mysql版)
2013/09/17 Javascript
js 模式窗口(模式对话框和非模式对话框)的使用介绍
2014/07/17 Javascript
Javascript基础教程之数据类型 (字符串 String)
2015/01/18 Javascript
jQuery实现网页抖动的菜单抖动效果
2015/08/07 Javascript
jQuery实用技巧必备(上)
2015/11/02 Javascript
Bootstrap每天必学之日期控制
2016/03/07 Javascript
js实现的页面加载完毕之前loading提示效果完整示例【附demo源码下载】
2016/08/02 Javascript
微信小程序 devtool隐藏的秘密
2017/01/21 Javascript
JS正则表达式验证中文字符
2017/05/08 Javascript
微信小程序日期选择器实例代码
2018/07/18 Javascript
vue + any-touch实现一个iscroll 实现拖拽和滑动动画效果
2019/04/08 Javascript
微信小程序后台持续定位功能使用详解
2019/08/23 Javascript
vue多页面项目中路由使用history模式的方法
2019/09/23 Javascript
使用Vue-cli 中为单独页面设置背景图片铺满全屏
2020/07/17 Javascript
微信小程序canvas实现签名功能
2021/01/19 Javascript
python不带重复的全排列代码
2013/08/13 Python
在Django的视图(View)外使用Session的方法
2015/07/23 Python
Python中getpass模块无回显输入源码解析
2018/01/11 Python
谈谈python中GUI的选择
2018/03/01 Python
python实现随机漫步算法
2018/08/27 Python
Django 创建后台,配置sqlite3教程
2019/11/18 Python
python复合条件下的字典排序
2020/12/18 Python
如何用python写个模板引擎
2021/01/14 Python
Mio Skincare法国官网:身体紧致及孕期身体护理
2018/04/04 全球购物
应届生求职简历的自我评价怎么写
2013/10/23 职场文书
国际贸易专业推荐信
2013/11/15 职场文书
员工工作自我评价
2014/09/26 职场文书
医学生自荐信范文
2015/03/05 职场文书