最近正在用Go語言做一個項目,今天在用http包讀取客戶端發過來的POST數據時遇到了一點小麻煩,就下面這段代碼,死活讀不到數據:
if r.ContentLength > 0 { var body []byte nRead, err := r.Body.Read(body) if err != nil { fmt.Println(err.Error()) } }
返回的錯誤值是EOF。通過檢查header信息,發現content-type是application/x-www-form-urlencoded。檢查Request信息也發現ContentLength的值大於0。仔細過了一遍前面的代碼,發現在剛開始處理請求的地方,為了輸出http.Request的所有信息,調用下面這個函數來解析Form數據:
r.ParseForm()
試着把這句注釋掉,可以讀到數據了!
查看了ParseForm的源代碼,發現它已經讀取了Request Body里的數據:
if r.Method == "POST" || r.Method == "PUT" { if r.Body == nil { return errors.New("missing form body") } ct := r.Header.Get("Content-Type") ct, _, err = mime.ParseMediaType(ct) switch { case ct == "application/x-www-form-urlencoded": var reader io.Reader = r.Body maxFormSize := int64(1<<63 - 1) if _, ok := r.Body.(*maxBytesReader); !ok { maxFormSize = int64(10 << 20) // 10 MB is a lot of text. reader = io.LimitReader(r.Body, maxFormSize+1) } b, e := ioutil.ReadAll(reader) if e != nil { if err == nil { err = e } break }
同時還要注意的有以下幾個函數:
func (r *Request) ParseMultipartForm(maxMemory int64) error func (r *Request) FormValue(key string) string func (r *Request) FormFile(key string)
它們可能會直接或間接的調用ParseForm,同樣會造成Body數據被讀取。雖說浪費了一些時間,但好在及時跳出了這個坑,也希望這個教訓能給大家一點幫助。