net/url.Values în Go

Parametrii unui query string sau ai unui formular: Get, Set, Add, Del, Has și Encode (codare sortată după cheie).

Sintaxă
type Values map[string][]string

func (v Values) Get(key string) string
func (v Values) Set(key, value string)
func (v Values) Add(key, value string)
func (v Values) Del(key string)
func (v Values) Has(key string) bool     // Go 1.17
func (v Values) Encode() string

Ce face net/url.Values

url.Values este un map de la nume la o listă de valori, ca un parametru să poată apărea de mai multe ori (?tag=go&tag=web). Îl primești de la u.Query(), url.ParseQuery sau r.Form și îl dai lui http.PostForm.

Get(k) returnează prima valoare sau "". Set(k, v) înlocuiește toate valorile, Add(k, v) adaugă una, Del(k) șterge cheia, iar Has(k) spune dacă cheia există (chiar cu valoare goală, spre deosebire de Get). Spre deosebire de http.Header, numele sunt sensibile la litere mari și mici.

Encode() produce textul codat, cu cheile sortate alfabetic: spațiul devine +, diacriticele devin %C8%99 etc. Rezultatul se pune după ? sau ca corp de formular.

Ce returnează

Get: string. Has: bool. Encode: textul codat. Set, Add, Del: nimic.

Exemple

Exemplul 1: Toate metodele

package main

import (
	"fmt"
	"net/url"
)

func main() {
	v := url.Values{}
	v.Set("oras", "Iași")
	v.Set("q", "cafenele & ceainării")
	v.Add("tag", "wifi")
	v.Add("tag", "terasă")
	v.Set("pagina", "")

	fmt.Println("Get oras:   ", v.Get("oras"))
	fmt.Println("Toate tag:  ", v["tag"])
	fmt.Println("Get pagina: ", v.Get("pagina") == "", "| Has pagina:", v.Has("pagina"))
	fmt.Println("Has Oras:   ", v.Has("Oras"), "(cheile țin cont de litere mari)")

	v.Del("pagina")
	fmt.Println("Encode:", v.Encode())
}

Rezultat

Get oras:    Iași
Toate tag:   [wifi terasă]
Get pagina:  true | Has pagina: true
Has Oras:    false (cheile țin cont de litere mari)
Encode: oras=Ia%C8%99i&q=cafenele+%26+ceain%C4%83rii&tag=wifi&tag=teras%C4%83

Exemplul 2: Valori citite dintr-un map literal

url.Values fiind un map, se poate scrie direct ca literal.

package main

import (
	"fmt"
	"net/url"
)

func main() {
	filtre := url.Values{
		"categorie": {"laptopuri"},
		"marca":     {"Lenovo", "Dell"},
		"pret":      {"2000-4000"},
	}
	fmt.Println("https://magazin.ro/produse?" + filtre.Encode())
	for _, m := range filtre["marca"] {
		fmt.Println("- marca:", m)
	}
}

Rezultat

https://magazin.ro/produse?categorie=laptopuri&marca=Lenovo&marca=Dell&pret=2000-4000
- marca: Lenovo
- marca: Dell

Greșeli frecvente

  • Folosești Get(k) != "" ca să afli dacă un parametru există: ?abonat= are cheia, dar valoarea goală. Folosește Has.
  • Scrii var v url.Values și apoi v.Set(...): map-ul este nil și programul se oprește cu panică. Inițializează cu url.Values{}.

Comenzi înrudite

  • net/url.URL.Query: Desface partea de după „?” a unei adrese într-un url.Values (map de la nume la valori).
  • net/url.ParseQuery: Desface un text de forma a=1&b=2 într-un url.Values și raportează prima eroare de codare.
  • net/url.QueryEscape: QueryEscape codează un text pentru query string (spațiu → +), PathEscape pentru o bucată de cale (spațiu → %20); QueryUnescape decodează.
  • 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.