net/http.Request.FormValue în Go

FormValue citește un câmp dintr-un formular sau din query string; ParseForm le citește pe toate în r.Form și r.PostForm.

Sintaxă
func (r *Request) FormValue(key string) string
func (r *Request) ParseForm() error
// după ParseForm: r.Form (query + corp), r.PostForm (doar corp)

Ce face net/http.Request.FormValue

r.FormValue("email") returnează prima valoare a câmpului email, căutată întâi în corpul unui formular trimis cu POST/PUT/PATCH (application/x-www-form-urlencoded sau multipart/form-data), apoi în query string (?email=...). Dacă lipsește, returnează textul gol. Apelează singur ParseForm și ignoră erorile.

r.ParseForm() citește explicit datele și le pune în r.Form (query + corp) și r.PostForm (doar corp). Este util când un câmp are mai multe valori (căsuțe bifate: r.Form["interese"]) sau când vrei să tratezi eroarea, de exemplu un corp prea mare.

Parametri

Parametru Descriere
key Numele câmpului din formular (atributul name).

Ce returnează

FormValue: prima valoare sau "". ParseForm: o eroare dacă datele nu pot fi citite.

Exemple

Exemplul 1: Formular de înscriere

package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"strings"
)

func inscriere(w http.ResponseWriter, r *http.Request) {
	nume := strings.TrimSpace(r.FormValue("nume"))
	oras := r.FormValue("oras")
	if nume == "" {
		http.Error(w, "numele este obligatoriu", http.StatusBadRequest)
		return
	}
	fmt.Fprintf(w, "Înscris: %s din %s (sursa: %s)", nume, oras, r.FormValue("sursa"))
}

func main() {
	corp := strings.NewReader("nume=Ana+Popescu&oras=Ia%C8%99i")
	req := httptest.NewRequest("POST", "/inscriere?sursa=newsletter", corp)
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	rec := httptest.NewRecorder()
	inscriere(rec, req)
	fmt.Println(rec.Code, rec.Body.String())

	rec = httptest.NewRecorder()
	inscriere(rec, httptest.NewRequest("GET", "/inscriere?oras=Cluj", nil))
	fmt.Print(rec.Code, " ", rec.Body.String())
}

Rezultat

200 Înscris: Ana Popescu din Iași (sursa: newsletter)
400 numele este obligatoriu

Exemplul 2: ParseForm și câmpuri cu mai multe valori

package main

import (
	"fmt"
	"net/http/httptest"
	"strings"
)

func main() {
	corp := strings.NewReader("interese=go&interese=mysql&interese=linux&nume=Radu")
	req := httptest.NewRequest("POST", "/profil?pagina=2", corp)
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	if err := req.ParseForm(); err != nil {
		fmt.Println("eroare:", err)
		return
	}
	fmt.Println("Form:     ", req.Form)
	fmt.Println("PostForm: ", req.PostForm)
	fmt.Println("Interese: ", req.Form["interese"])
	fmt.Println("FormValue:", req.FormValue("interese"), "(doar prima)")
}

Rezultat

Form:      map[interese:[go mysql linux] nume:[Radu] pagina:[2]]
PostForm:  map[interese:[go mysql linux] nume:[Radu]]
Interese:  [go mysql linux]
FormValue: go (doar prima)

Greșeli frecvente

  • Trimiți formularul fără antetul Content-Type: application/x-www-form-urlencoded (de exemplu din cod): corpul nu este citit și FormValue returnează gol.
  • Folosești FormValue pentru JSON. Corpurile JSON se citesc cu json.NewDecoder(r.Body).Decode(&v).
  • Folosești FormValue pentru căsuțe cu mai multe valori: primești doar prima. Folosește r.Form["camp"] după ParseForm.

Comenzi înrudite

  • net/http.Request: Structura unei cereri HTTP: metoda, URL-ul, antetele, corpul și contextul (Context()) care se anulează când clientul pleacă.
  • net/http.Post: Post trimite date (ex. JSON) cu tipul de conținut dat; PostForm trimite un formular codat ca application/x-www-form-urlencoded.
  • net/url.Values: Parametrii unui query string sau ai unui formular: Get, Set, Add, Del, Has și Encode (codare sortată după cheie).
  • net/http.MaxBytesReader: Limitează mărimea corpului unei cereri: citirea peste n octeți returnează eroare *http.MaxBytesError.