63 / 68

net/http

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.

example.go
import "net/http"

1. Oddiy HTTP server yaratish

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:

example.go
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.


2. So'rov parametrlarini o'qish

example.go
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.


3. Bir nechta yo'l (route) uchun http.ServeMux

Katta dasturlarda har bir yo'lni alohida-alohida ro'yxatdan o'tkazish uchun ServeMux (multiplexer) ishlatiladi:

example.go
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)
}

4. JSON javob qaytaruvchi API yozish

Zamonaviy backend'larning aksariyati JSON formatida javob qaytaradi. Buning uchun encoding/json bilan birga ishlatamiz:

example.go
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:

json
{"text":"Qabul qilindi: Salom"}

5. HTTP klient: tashqi manbadan ma'lumot olish (GET)

net/http nafaqat server, balki HTTP so'rov yuboruvchi (klient) sifatida ham ishlatiladi:

example.go
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 odatda defer resp.Body.Close() orqali darhol, err tekshirilgandan keyin qilinadi).


6. Ma'lumot yuborish: POST so'rovi

example.go
package 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))
}

7. Vaqt chegarasi (timeout) bilan klient yaratish

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:

example.go
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)
}

Xulosa: qachon qaysi funksiya kerak?

VazifaFunksiya
Oddiy server ishga tushirishhttp.HandleFunc() + http.ListenAndServe()
Bir nechta yo'lni tartibli boshqarishhttp.NewServeMux()
URL parametrini o'qishr.URL.Query().Get("nomi")
So'rov tanasidan JSON o'qishjson.NewDecoder(r.Body).Decode(&v)
JSON javob qaytarishjson.NewEncoder(w).Encode(v)
Tashqi manbadan ma'lumot olishhttp.Get(url)
Ma'lumot yuborishhttp.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 shu net/http paketiga tayanadi.