net/http.ListenAndServe în Go

Pornește un server web pe adresa dată (ex. ":8080") și răspunde la cereri cu handler-ul dat; rulează până la oprire.

Sintaxă
import "net/http"

func ListenAndServe(addr string, handler Handler) error

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ă ListenAndServe crezâ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 ListenAndServe simplu: nu are limite de timp, deci clienții lenți pot ține conexiuni deschise la nesfârșit. Folosește http.Server cu ReadTimeout și WriteTimeout.

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).