对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中semaphore(信号量)源码
Apr 03 Golang
用golang如何替换某个文件中的字符串
Apr 25 Golang
Go语言带缓冲的通道实现
Apr 26 Golang
golang 在windows中设置环境变量的操作
Apr 29 Golang
解决golang结构体tag编译错误的问题
May 02 Golang
go语言中fallthrough的用法说明
May 06 Golang
goland 设置project gopath的操作
May 06 Golang
go 实现简易端口扫描的示例
May 22 Golang
Go 中的空白标识符下划线
Mar 25 Golang
Go归并排序算法的实现方法
Apr 06 Golang
Golang并发工具Singleflight
May 06 Golang
Go调用Rust方法及外部函数接口前置
Jun 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
Uchome1.2 1.5 代码学习 common.php
2009/04/24 PHP
基于JQuery+PHP编写砸金蛋中奖程序
2015/09/08 PHP
在 Laravel 6 中缓存数据库查询结果的方法
2019/12/11 PHP
疯掉了,尽然有js写的操作系统
2007/04/23 Javascript
extJs 文本框后面加上说明文字+下拉列表选中值后触发事件
2009/11/27 Javascript
js实现遮罩层划出效果是生成div而不是显示
2014/07/29 Javascript
一款基jquery超炫的动画导航菜单可响应单击事件
2014/11/02 Javascript
jquery中map函数遍历数组用法实例
2015/05/18 Javascript
JS组件Bootstrap Select2使用方法详解
2020/04/17 Javascript
JS中Json数据的处理和解析JSON数据的方法详解
2016/06/29 Javascript
微信js-sdk分享功能接口常用逻辑封装示例
2016/10/13 Javascript
AngularJS指令用法详解
2016/11/02 Javascript
老生常谈原生JS执行环境与作用域
2016/11/22 Javascript
webpack学习教程之publicPath路径问题详解
2017/06/17 Javascript
全面解析jQuery中的$(window)与$(document)的用法区别
2017/08/15 jQuery
解决vue的 v-for 循环中图片加载路径问题
2018/09/03 Javascript
vue 2.1.3 实时显示当前时间,每秒更新的方法
2018/09/16 Javascript
JavaScript函数Call、Apply原理实例解析
2020/02/17 Javascript
vue实现循环滚动列表
2020/06/30 Javascript
vue-video-player 断点续播的实现
2021/02/01 Vue.js
Python学习笔记_数据排序方法
2014/05/22 Python
python图片验证码生成代码
2016/07/02 Python
Python利用IPython提高开发效率
2016/08/10 Python
Python抓取手机号归属地信息示例代码
2016/11/28 Python
Python AES加密实例解析
2018/01/18 Python
python和opencv实现抠图
2018/07/18 Python
numpy添加新的维度:newaxis的方法
2018/08/02 Python
django框架使用方法详解
2019/07/18 Python
关于python3中setup.py小概念解析
2019/08/22 Python
快速了解Python开发环境Spyder
2020/06/29 Python
Python如何在bool函数中取值
2020/09/21 Python
详解pycharm的python包opencv(cv2)无代码提示问题的解决
2021/01/29 Python
解释下列WebService名词:WSDL、SOAP、UDDI
2012/06/22 面试题
就业推荐表自我鉴定范文
2014/03/21 职场文书
2019职场单身人才调研报告:互联网行业单身比例最高
2019/08/07 职场文书
如何在CSS中绘制曲线图形及展示动画
2021/05/24 HTML / CSS