http.request的三个属性Form、PostForm、MultipartForm:
Form:存储了post、put和get参数,在使用之前需要调用ParseForm方法。
PostForm:存储了post、put参数,在使用之前需要调用ParseForm方法。
MultipartForm:存储了包含了文件上传的表单的post参数,在使用前需要调用ParseMultipartForm方法。
获取Get参数
实例
package main import ( "fmt" "log" "net/http" ) func sayHelloHandler(w http.ResponseWriter, r *http.Request) { r.ParseForm()//解析url传递的参数,对于POST则解析响应包的主体(request body) //注意:如果没有调用ParseForm方法,下面无法获取表单的数据 uid := r.Form["uid"] fmt.Println(uid) } func main() { http.HandleFunc("/", sayHelloHandler) // 设置访问路由 log.Fatal(http.ListenAndServe(":8080", nil)) }
用postman测试,提交http://localhost:8080/?uid=111
服务端输出 :[111]
提交: http://localhost:8080/?uid=111&uid=222
服务端输出:[111 222]
小结:r.Form是url.Values字典类型,r.Form[“id”]取到的是一个数组类型。因为http.request在解析参数的时候会将同名的参数都放进同一个数组里。
因为r.Form包含了GET、POST参数,POST参数优先,那么想只获取GET参数怎么办?可以改进代码:
query := r.URL.Query() uid := query["uid"][0] fmt.Println(uid)
以上代码意思是获取Url问号后地代码。
获取POST参数
这里有两种情况:
普通的post表单请求,Content-Type=application/x-www-form-urlencoded
有文件上传的表单,Content-Type=multipart/form-data
第一种情况,只获取文本类型参数用以下代码:
uid := r.PostFormValue("uid") fmt.Println(uid)
或
r.ParseForm() uid := r.PostForm["uid"] fmt.Println(uid)
r.PostFormValue()和r.PostForm区别是r.PostFormValue()只获取第一个参数,r.PostForm获取的是一个数组。
第二种情况,获取文本类型参数用以下代码:
r.ParseMultipartForm(32 << 20) if r.MultipartForm != nil { values := r.MultipartForm.Value["uid"] fmt.Println(values) }
处理上传单个文件
package main import ( "log" "net/http" "os" "io" ) func sayHelloHandler(w http.ResponseWriter, r *http.Request) { // 根据字段名获取表单文件 formFile, header, err := r.FormFile("uploadfile") if err != nil { log.Printf("Get form file failed: %s\n", err) return } defer formFile.Close() // 创建保存文件 destFile, err := os.Create("./upload/" + header.Filename) if err != nil { log.Printf("Create failed: %s\n", err) return } defer destFile.Close() // 读取表单文件,写入保存文件 _, err = io.Copy(destFile, formFile) if err != nil { log.Printf("Write file failed: %s\n", err) return } //fmt.Fprintf(w, "Hello world!\n") //这个写入到w的是输出到客户端的 } func main() { http.HandleFunc("/", sayHelloHandler) // 设置访问路由 log.Fatal(http.ListenAndServe(":8080", nil)) }
处理上传多个文件
package main import ( "fmt" "io" "log" "net/http" "os" ) func sayHelloHandler(w http.ResponseWriter, r *http.Request) { //设置内存大小 r.ParseMultipartForm(32 << 20) //获取上传的文件组 files := r.MultipartForm.File["uploadfile"] len := len(files) for i := 0; i < len; i++ { //打开上传文件 file, err := files[i].Open() defer file.Close() if err != nil { log.Fatal(err) } //创建上传目录 os.Mkdir("./upload", os.ModePerm) //创建上传文件 cur, err := os.Create("./upload/" + files[i].Filename) defer cur.Close() if err != nil { log.Fatal(err) } io.Copy(cur, file) fmt.Println(files[i].Filename) //输出上传的文件名 } //fmt.Fprintf(w, "Hello world!\n") //这个写入到w的是输出到客户端的 } func main() { http.HandleFunc("/", sayHelloHandler) //设置访问路由 log.Fatal(http.ListenAndServe(":8080", nil)) }