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: %sn", err)
      return
   }
   defer formFile.Close()
   // 创建保存文件
   destFile, err := os.Create("./upload/" + header.Filename)
   if err != nil {
      log.Printf("Create failed: %sn", err)
      return
   }
   defer destFile.Close()
   
   // 读取表单文件,写入保存文件
   _, err = io.Copy(destFile, formFile)
   if err != nil {
      log.Printf("Write file failed: %sn", 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))
}