天天看點

Golang請求資料處理

擷取參數

我們經常需要擷取使用者傳遞的資料,包括

GET

POST

等方式的請求。你可以通過如下方式擷取資料:

通過

r.Form.Get("參數名")

r.PostForm.Get("參數名")

擷取對應字段的值,r表示伺服器接收或由用戶端發送的

HTTP

請求。在Go标準包

net/http

中的

request.go

檔案中可以看到該結構體的定義,其中與今天讨論有關的字段有

type Request struct {
	Body 			io.ReadCloser
    Form 			url.Values  
    PostForm 		url.Values
    MultipartForm 	*multipart.Form
}
           

Body

字段後面的這三個字段都需要依賴其他方法,前兩者需要調用

ParseForm()

方法,後者需要調用

ParseMultipartForm()

方法。

  • 對于所有的請求,

    ParseForm

    URL

    解析原始查詢,對于

    POST

    PUT

    PATCH

    請求,它還會将請求解析為表單,并将結果放入

    r.PostForm

    r.Form

    中。請求

    body

    參數優先于

    r.Form

    中的

    URL

    查詢字元串值。

    對于其他

    HTTP

    方法,或者當

    Content-Type

    不是

    application/x-www-form-urlencoded

    時,該方法不會讀取請求

    body

    ,同時也不會将

    r.PostForm

    初始化為非零空值。

    如果請求

    body

    的大小沒有提前限定,那麼它的最大值為

    10MB

  • ParseMultipartForm

    解析表單屬性

    enctype

    multipart/form-data

    的内容。

    func (r *Request) ParseMultipartForm(maxMemory int64) error

    ,調用

    ParseMultipartForm

    之後,上傳的檔案存儲在

    maxMemory

    大小的記憶體裡面,如果檔案大小超過了

    maxMemory

    ,那麼剩下的部分将存儲在系統的臨時檔案中。

直接解析到struct

當請求不能用上面的方法擷取時,可以使用

ioutil.ReadAll(r.Body)

讀取請求中的

body

。再通過

struct

的字段名或

tag

body

中對應字段直接解析到

struct

。定義

struct

時,字段名後如果有

form

這個

tag

,則會以把

form

表單裡的

name

tag

的名稱一樣的字段指派給這個字段,否則就會把

form

表單裡與字段名一樣的表單内容指派給這個字段。

如果要忽略一個字段,有兩種辦法:一是字段名小寫開頭,二是

form

标簽的值設定為

-

完整代碼

main.go
package main

import (
	"net/http"
	"fmt"
	"io/ioutil"
	"encoding/json"
	"html/template"
)

type Test struct {
	NickName string `json:"nickname"`
	Phone    string `json:"phone"`
	PassWord string `json:"password"`
}

func main() {
	http.HandleFunc("/test", testFunc)
	http.HandleFunc("/testdata", testData)
	http.ListenAndServe(":8000", nil)
}

func testFunc(w http.ResponseWriter, r *http.Request) {
	t, _ := template.ParseFiles("templates/test.html")
	t.Execute(w, nil)
}

func testData(w http.ResponseWriter, r *http.Request) {
	var test Test
	r.ParseForm()
	test.NickName = r.Form.Get("nickname")
	if test.NickName == "" {
		data, err := ioutil.ReadAll(r.Body)
		if err != nil {
			fmt.Println(err)
			return
		}
		err = json.Unmarshal(data, &test)
		if err != nil {
			fmt.Println(err)
			return
		}
		fmt.Fprintf(w, "====>%s %s %s", test.NickName, test.Phone, test.PassWord)
	} else {
		test.Phone = r.Form.Get("phone")
		test.PassWord = r.Form.Get("password")
		fmt.Fprintf(w, "%s %s %s", test.NickName, test.Phone, test.PassWord)
	}
}
           
test.html
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>test</title>
</head>
<body>
<form action="/testdata" method="post">
    NickName:<br>
    <input type="text" name="nickname" value="請輸入昵稱">
    <br>
    Phone:<br>
    <input type="text" name="phone" value="請輸入手機号">
    <br>
    PassWord:<br>
    <input type="text" name="password" value="請輸入密碼">
    <br><br>
    <input type="submit" value="submit">
</form>
</body>
</html>