Ce face net/http.ListenAndServe
http.ListenAndServe(":8080", nil) deschide portul 8080 pe toate interfețele și servește cereri până când programul este oprit. Fiecare cerere este tratată într-un goroutine separat, deci serverul răspunde la mai mulți clienți în paralel fără cod în plus.
Al doilea parametru este handler-ul care primește toate cererile. Cu nil se folosește http.DefaultServeMux, routerul global în care înregistrezi rute cu http.HandleFunc. În aplicații reale creezi propriul router cu http.NewServeMux() și îl dai aici.
Funcția returnează doar la eroare (de exemplu portul este deja ocupat), iar eroarea nu este niciodată nil. De aceea se scrie de obicei log.Fatal(http.ListenAndServe(...)). Pentru limite de timp și oprire curată folosește http.Server. În testele și exemplele de pe această pagină, serverul pornește cu httptest.NewServer, care alege singur un port liber.
Parametri
| Parametru | Descriere |
|---|---|
addr |
Adresa și portul: ":8080" (toate interfețele), "127.0.0.1:8080" (doar local). |
handler |
Handler-ul pentru toate cererile, sau nil pentru http.DefaultServeMux. |
Ce returnează
O eroare (întotdeauna diferită de nil) când serverul nu mai poate rula.
Exemple
Exemplul 1: Primul server web
Programul rulează până îl oprești cu Ctrl+C. Deschide în browser http://localhost:8080/?nume=Ana.
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
nume := r.URL.Query().Get("nume")
if nume == "" {
nume = "vizitator"
}
fmt.Fprintf(w, "Salut, %s!\n", nume)
})
log.Println("Server pornit pe http://localhost:8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
Rezultat (în terminal și în browser)
2026/10/19 12:00:00 Server pornit pe http://localhost:8080
# în browser, la http://localhost:8080/?nume=Ana:
Salut, Ana!
Exemplul 2: Același handler, testat cu httptest
httptest.NewServer pornește un server real pe un port liber de pe calculatorul tău; http.Get trimite cereri la el.
package main
import (
"fmt"
"io"
"net/http"
"net/http/httptest"
)
func salut(w http.ResponseWriter, r *http.Request) {
nume := r.URL.Query().Get("nume")
if nume == "" {
nume = "vizitator"
}
fmt.Fprintf(w, "Salut, %s!\n", nume)
}
func main() {
srv := httptest.NewServer(http.HandlerFunc(salut))
defer srv.Close()
for _, cale := range []string{"/", "/?nume=Ana"} {
resp, err := http.Get(srv.URL + cale)
if err != nil {
fmt.Println("eroare:", err)
return
}
corp, _ := io.ReadAll(resp.Body)
resp.Body.Close()
fmt.Printf("%-12s %s %s", cale, resp.Status, corp)
}
}
Rezultat
/ 200 OK Salut, vizitator!
/?nume=Ana 200 OK Salut, Ana!
Exemplul 3: Portul este deja ocupat
Dacă alt program folosește portul, ListenAndServe returnează imediat eroarea.
package main
import (
"fmt"
"net/http"
)
func main() {
err := http.ListenAndServe(":8080", nil)
fmt.Println("Serverul s-a oprit:", err)
}
Rezultat posibil (diferă la fiecare rulare)
Serverul s-a oprit: listen tcp :8080: bind: address already in use
Greșeli frecvente
- Scrii codul după
ListenAndServecrezând că rulează: funcția blochează cât timp serverul merge. Pornește alte sarcini înainte, în goroutine. - Ignori eroarea returnată: programul se termină fără niciun mesaj dacă portul este ocupat. Scrie
log.Fatal(http.ListenAndServe(...)). - Pui serverul în producție cu
ListenAndServesimplu: nu are limite de timp, deci clienții lenți pot ține conexiuni deschise la nesfârșit. Foloseștehttp.ServercuReadTimeoutșiWriteTimeout.
Comenzi înrudite
net/http.HandleFunc: Înregistrează o rută în routerul global (DefaultServeMux): HandleFunc primește o funcție, Handle un Handler.net/http.NewServeMux: Creează un router (ServeMux) propriu care alege handler-ul după metoda și calea cererii; HandleFunc și Handle adaugă rute.net/http.Server: Serverul HTTP configurabil: adresă, handler, limite de timp; ListenAndServe îl pornește, Shutdown îl oprește curat.net/http.ResponseWriter: Interfața prin care handler-ul construiește răspunsul: antete (Header), cod de stare (WriteHeader) și corp (Write).