net/http paketi
net/http — Goning eng kuchli tomonlaridan biri hisoblanadi: u yordamida hech qanday tashqi kutubxonasiz to'liq HTTP server yoki HTTP so'rov yuboruvchi klient yozish mumkin. Aynan shu paket tufayli Go veb-backend dasturlash uchun juda mashhur til hisoblanadi.
import "net/http"
HTTP serverning eng asosiy tuzilishi ikki qismdan iborat: handler (so'rov kelganda nima qilishni bildiruvchi funksiya) va uni ma'lum "yo'l" (route)ga bog'lash:
package main
import (
"fmt"
"net/http"
)
// handler — HTTP so'rov kelganda ishga tushadigan funksiya
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Salom, Go Dasturchi!")
}
func main() {
// "/salom" manziliga so'rov kelganda helloHandler ishlaydi
http.HandleFunc("/salom", helloHandler)
fmt.Println("Server 8080-portda ishga tushdi...")
// serverni ishga tushiramiz (bu qator dastur to'xtamaguncha bloklab turadi)
http.ListenAndServe(":8080", nil)
}
Dasturni ishga tushirib, brauzerda http://localhost:8080/salom manziliga kirsangiz, ekranda "Salom, Go Dasturchi!" yozuvini ko'rasiz.
[!NOTE]
http.ListenAndServe()chaqirilgan zahoti dastur "to'xtab", so'rovlarni kutishni boshlaydi (u faqat xatolik yuz berganda yoki dastur majburan yopilganda qaytadi). Shuning uchun bu misolni onlayn muharrirda ishga tushirsangiz, u "abadiy" ishlayotgandek ko'rinadi — bu normal holat, chunki server aynan shunday ishlashi kerak.
func greetHandler(w http.ResponseWriter, r *http.Request) {
// URL'dagi ?name=Ali kabi so'rov parametrini o'qiymiz
name := r.URL.Query().Get("name")
if name == "" {
name = "mehmon"
}
fmt.Fprintf(w, "Assalomu alaykum, %s!", name)
}
Agar http://localhost:8080/greet?name=Ali manziliga kirilsa, natija: "Assalomu alaykum, Ali!". Agar name parametri berilmasa, mehmon so'zi ishlatiladi.
http.ServeMuxKatta dasturlarda har bir yo'lni alohida-alohida ro'yxatdan o'tkazish uchun ServeMux (multiplexer) ishlatiladi:
package main
import (
"fmt"
"net/http"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Bosh sahifa")
})
mux.HandleFunc("/haqida", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Bu — Go Dasturchi platformasi haqida sahifa")
})
http.ListenAndServe(":8080", mux)
}
Zamonaviy backend'larning aksariyati JSON formatida javob qaytaradi. Buning uchun encoding/json bilan birga ishlatamiz:
package main
import (
"encoding/json"
"net/http"
)
type Message struct {
Text string `json:"text"`
}
func echoHandler(w http.ResponseWriter, r *http.Request) {
var msg Message
// so'rov tanasidagi (body) JSON'ni struct'ga o'qib olamiz
json.NewDecoder(r.Body).Decode(&msg)
w.Header().Set("Content-Type", "application/json")
// javobni JSON ko'rinishida yozamiz
json.NewEncoder(w).Encode(Message{Text: "Qabul qilindi: " + msg.Text})
}
func main() {
http.HandleFunc("/echo", echoHandler)
http.ListenAndServe(":8080", nil)
}
Agar /echo manziliga {"text":"Salom"} ko'rinishidagi JSON bilan POST so'rovi yuborilsa, javob quyidagicha bo'ladi:
Javob:
{"text":"Qabul qilindi: Salom"}
GET)net/http nafaqat server, balki HTTP so'rov yuboruvchi (klient) sifatida ham ishlatiladi:
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
resp, err := http.Get("https://example.com")
if err != nil {
fmt.Println("Xatolik:", err)
return
}
defer resp.Body.Close() // javob tanasini har doim yopish shart!
body, _ := io.ReadAll(resp.Body)
fmt.Println("Status:", resp.StatusCode)
fmt.Println("Javob uzunligi:", len(body))
}
[!IMPORTANT]
resp.Body.Close()ni hech qachon unutmang! Agar javob tanasi yopilmasa, tarmoq ulanishi "ochiq" holda qolib ketaveradi va dastur uzoq ishlaganda resurslar tugab qolishi mumkin (bu odatdadefer resp.Body.Close()orqali darhol,errtekshirilgandan keyin qilinadi).
POST so'rovipackage main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
type Message struct {
Text string `json:"text"`
}
func main() {
payload, _ := json.Marshal(Message{Text: "Salom"})
resp, err := http.Post(
"https://example.com/api/echo",
"application/json",
bytes.NewReader(payload),
)
if err != nil {
fmt.Println(err)
return
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
Standart http.Get()/http.Post() sukut bo'yicha hech qanday timeout'ga ega emas — agar server javob bermasa, dastur abadiy kutib qolishi mumkin! Shuning uchun ishlab chiqarish (production) kodida har doim o'z klientingizni timeout bilan yaratish tavsiya etiladi:
package main
import (
"fmt"
"net/http"
"time"
)
func main() {
client := &http.Client{
Timeout: 5 * time.Second, // 5 soniyadan ko'p kutmaydi
}
resp, err := client.Get("https://example.com")
if err != nil {
fmt.Println("Xatolik (yoki timeout):", err)
return
}
defer resp.Body.Close()
fmt.Println("Status:", resp.StatusCode)
}
| Vazifa | Funksiya |
|---|---|
| Oddiy server ishga tushirish | http.HandleFunc() + http.ListenAndServe() |
| Bir nechta yo'lni tartibli boshqarish | http.NewServeMux() |
| URL parametrini o'qish | r.URL.Query().Get("nomi") |
| So'rov tanasidan JSON o'qish | json.NewDecoder(r.Body).Decode(&v) |
| JSON javob qaytarish | json.NewEncoder(w).Encode(v) |
| Tashqi manbadan ma'lumot olish | http.Get(url) |
| Ma'lumot yuborish | http.Post(url, turi, tana) |
| Timeout bilan xavfsiz klient | &http.Client{Timeout: ...} |
[!NOTE] Kichik va o'rta loyihalar uchun
net/httpning o'zi to'liq yetarli. Faqat juda murakkab marshrutlash (masalan,/users/{id}/posts/{postId}kabi dinamik yo'llar) kerak bo'lganda, jamiyat tomonidan yaratilgan qo'shimcha kutubxonalar (masalan,chi,gin) ishlatiladi — lekin ularning barchasi ham asosda aynan shunet/httppaketiga tayanadi.