对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语言中的UTF-8实现
Apr 26 Golang
解决Golang中ResponseWriter的一个坑
Apr 27 Golang
golang 在windows中设置环境变量的操作
Apr 29 Golang
golang slice元素去重操作
Apr 30 Golang
goland设置颜色和字体的操作
May 05 Golang
go语言中fallthrough的用法说明
May 06 Golang
Golang中异常处理机制详解
Jun 08 Golang
入门学习Go的基本语法
Jul 07 Golang
Go语言应该什么情况使用指针
Jul 25 Golang
Go web入门Go pongo2模板引擎
May 20 Golang
Go Grpc Gateway兼容HTTP协议文档自动生成网关
Jun 16 Golang
Go语言怎么使用变长参数函数
Jul 15 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
如何开发一个虚拟域名系统
2006/10/09 PHP
使用PHP Socket写的POP3类
2013/10/30 PHP
php实现的简单日志写入函数
2015/03/31 PHP
Yii2框架控制器、路由、Url生成操作示例
2019/05/27 PHP
Mootools 1.2教程 滚动条(Slider)
2009/09/15 Javascript
jQuery 验证插件 Web前端设计模式(asp.net)
2010/10/17 Javascript
JavaScript中“过于”犀利地for/in循环使用示例
2013/10/22 Javascript
JavaScript两种跨域技术全面介绍
2014/04/16 Javascript
js实现百度联盟中一款不错的图片切换效果完整实例
2015/03/04 Javascript
jQuery+AJAX实现无刷新下拉加载更多
2015/07/03 Javascript
jQuery实现连续动画效果实例分析
2015/10/09 Javascript
jQuery动画效果实现图片无缝连续滚动
2016/01/12 Javascript
nodejs入门教程三:调用内部和外部方法示例
2017/04/24 NodeJs
基于vue+ bootstrap实现图片上传图片展示功能
2017/05/17 Javascript
详解AngularJS controller调用factory
2017/05/19 Javascript
React中Ref 的使用方法详解
2020/04/28 Javascript
JavaScript禁止右击保存图片,禁止拖拽图片的实现代码
2020/04/28 Javascript
JavaScript闭包原理与用法学习笔记
2020/05/29 Javascript
通过实例解析jQ Ajax操作相关原理
2020/09/23 Javascript
Vue双向数据绑定(MVVM)的原理
2020/10/03 Javascript
在vue项目中 实现定义全局变量 全局函数操作
2020/10/26 Javascript
微信小程序实现电影App导航和轮播
2020/11/30 Javascript
js实现随机点名
2021/01/19 Javascript
详解Python3中的Sequence type的使用
2015/08/01 Python
Python切片操作去除字符串首尾的空格
2019/04/22 Python
Django中自定义模型管理器(Manager)及方法
2019/09/23 Python
使用pyinstaller逆向.pyc文件
2019/12/20 Python
html5使用Canvas绘图的使用方法
2017/11/21 HTML / CSS
html5+CSS3+JS实现七夕言情功能代码
2017/08/28 HTML / CSS
春季防火方案
2014/05/10 职场文书
群众路线个人对照检查材料
2014/09/23 职场文书
2014年党的群众路线活动个人整改措施
2014/10/28 职场文书
2015年乡镇卫生院妇幼保健工作总结
2015/05/19 职场文书
食堂卫生管理制度
2015/08/04 职场文书
城镇居民医疗保险工作总结
2015/08/10 职场文书
担保书格式范文
2015/09/22 职场文书