http.HandleFunc va http.ListenAndServe
Go’da har qanday web server ikki qadamdan boshlanadi. Avval qaysi yo‘lga qaysi funksiya javob berishini aytamiz. Keyin serverni ishga tushirib, portni tinglashni boshlaymiz. Birinchi qadamni http.HandleFunc, ikkinchisini http.ListenAndServe bajaradi.
Bu darsda ikkala funksiyani ichidan ko‘rib chiqamiz: ular aslida nima qiladi, qanday xatolar qaytaradi va serverni qanday qilib to‘g‘ri to‘xtatish kerak.
Eng kichik server
| main.go | |
|---|---|
Boshqa terminalda:
Kodda ikkita muhim qator bor. Ularni navbatma-navbat ko‘ramiz.
http.HandleFunc
Funksiya ikki argument oladi:
pattern— qaysi yo‘l uchun ekanini bildiruvchi qolip, masalan"/salom"yoki"GET /books";handler— shu yo‘lga so‘rov kelganda chaqiriladigan funksiya.
http.HandleFunc handlerni global http.DefaultServeMux routeriga qo‘shadi. Ichki ko‘rinishi taxminan quyidagicha:
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
Handler funksiyaning imzosi
Handler har doim bir xil imzoga ega bo‘ladi:
Funksiya hech narsa qaytarmaydi. Javob w orqali yoziladi. So‘rov haqidagi ma’lumot esa r ichida keladi.
Funksiya nomi muhim emas. Anonim funksiya ham ishlatish mumkin:
http.HandleFunc("/vaqt", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, time.Now().Format(time.DateTime))
})
HandleFunc va Handle farqi
Routerga handler qo‘shishning ikki usuli bor:
http.HandleFunc("/a", funksiya) // func(w, r) qabul qiladi
http.Handle("/b", handlerObyekt) // http.Handler interfeysini qabul qiladi
Handle — ServeHTTP metodiga ega obyekt uchun. HandleFunc — oddiy funksiya uchun. Aslida HandleFunc ichida funksiya http.HandlerFunc turiga o‘tkaziladi va Handlega beriladi. Demak, ikkalasi bir xil natijaga olib keladi.
Bir pattern ikki marta qo‘shilsa
Bir xil pattern ikki marta ro‘yxatdan o‘tkazilsa, dastur panic bilan to‘xtaydi:
http.HandleFunc("/salom", salom)
http.HandleFunc("/salom", boshqaSalom) // panic: pattern "/salom" ... conflicts with pattern "/salom"
Bu xato server ishga tushishidan oldin, dastur boshlanishida yuz beradi. Shuning uchun uni sezmay qolish qiyin.
http.ListenAndServe
Funksiya berilgan manzilda TCP ulanishlarni tinglaydi va har bir so‘rovni handlerga uzatadi.
Manzil (addr)
| Qiymat | Ma’nosi |
|---|---|
":8080" |
Barcha tarmoq interfeyslarida 8080-port |
"localhost:8080" |
Faqat shu kompyuterdan kelgan ulanishlar |
"127.0.0.1:8080" |
Xuddi yuqoridagidek, IPv4 manzil bilan |
"0.0.0.0:8080" |
Barcha IPv4 interfeyslar |
"" |
Standart HTTP porti, ya’ni :80 |
Ishlab chiqish paytida localhost:8080 xavfsizroq: server tarmoqdagi boshqa kompyuterlarga ko‘rinmaydi. Serverga yoki konteynerga joylashtirganda odatda :8080 ishlatiladi.
Handler (handler)
Ikkinchi argument — barcha so‘rovlarni qabul qiladigan handler. nil berilsa, http.DefaultServeMux ishlatiladi. O‘z router’ingiz bo‘lsa, shu yerga beriladi:
Bloklovchi chaqiruv
ListenAndServe server ishlab turgan vaqt davomida qaytmaydi. Undan keyingi qatorlar faqat server to‘xtaganda bajariladi:
Shu sababli serverni ishga tushirish odatda main funksiyasining oxirida turadi. Undan oldin barcha handlerlar ro‘yxatdan o‘tkazilgan bo‘lishi kerak.
Har bir so‘rov alohida goroutine’da
Server har bir yangi ulanish uchun alohida goroutine ishga tushiradi. Ya’ni bir vaqtda kelgan yuzta so‘rov parallel qayta ishlanadi.
Bu qulay, lekin bitta muhim oqibati bor: bir nechta handler umumiy o‘zgaruvchini o‘zgartirsa, data race yuzaga keladi.
counter o‘zgaruvchisi barcha so‘rovlar uchun umumiy. Shuning uchun unga murojaat sync.Mutex bilan himoyalangan. Mutex’siz yozilgan kodni go run -race main.go bilan ishga tushirib, bir nechta so‘rov yuborsangiz, race detector ogohlantirish beradi. Bu mavzu Mutex darsida batafsil yoritilgan.
Xatoni tekshirish
ListenAndServe doim nil bo‘lmagan xato qaytaradi. Xato ikki holatda keladi:
- Server umuman ishga tushmadi: port band, ruxsat yo‘q yoki manzil noto‘g‘ri.
- Server
ShutdownyokiClosebilan to‘xtatildi. Bu holatdahttp.ErrServerClosedqaytadi.
Eng oddiy usul — xatoni log.Fatal bilan chiqarish:
Port band bo‘lsa, shunday xabar chiqadi:
Warning
http.ListenAndServe(":8080", nil) natijasini tekshirmaslik keng tarqalgan xato. Port band bo‘lsa, dastur hech narsa demasdan darhol tugaydi va nima bo‘lganini tushunish qiyin bo‘ladi.
O‘z http.Serveringiz bilan
Production’da http.ListenAndServe o‘rniga http.Server yaratiladi. Sababi — timeoutlar va serverni to‘g‘ri to‘xtatish imkoniyati:
srv := &http.Server{
Addr: ":8080",
Handler: mux,
ReadHeaderTimeout: 5 * time.Second,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 60 * time.Second,
}
err := srv.ListenAndServe()
srv.ListenAndServe() xuddi paketdagi http.ListenAndServe kabi ishlaydi. Farqi shundaki, barcha sozlamalar sizning qo‘lingizda.
Serverni to‘g‘ri to‘xtatish (graceful shutdown)
Terminalda Ctrl+C bosilsa, dastur darhol o‘ladi. Shu paytda qayta ishlanayotgan so‘rovlar yarim yo‘lda uziladi. Masalan, foydalanuvchi buyurtma bergan, ma’lumot bazaga yozilmoqda, lekin javob yetib bormadi.
Graceful shutdown — serverni tartib bilan to‘xtatish. Bunda server yangi ulanishlarni qabul qilishni to‘xtatadi, boshlangan so‘rovlarning tugashini kutadi va shundan keyin chiqadi.
Misol
Sinab ko‘ring: serverni ishga tushiring, curl http://localhost:8080/sekin yuboring va javob kelishini kutmasdan server terminalida Ctrl+C bosing.
2026/09/30 10:00:00 Server: http://localhost:8080
^C2026/09/30 10:00:01 To‘xtatish signali keldi, server yopilmoqda...
2026/09/30 10:00:03 Server to‘xtadi
curl baribir Tayyor javobini oladi. Server so‘rov tugashini kutib, keyin to‘xtadi.
Kod qanday ishlaydi?
srv.ListenAndServe()goroutine ichida chaqiriladi. Shundamainbloklanmaydi va signalni kutishi mumkin.signal.NotifyContext—SIGINTyokiSIGTERMkelganda bekor bo‘ladigancontextqaytaradi.<-ctx.Done()shu signalni kutadi.srv.Shutdown(shutdownCtx)— yangi ulanishlarni qabul qilishni to‘xtatadi va faol so‘rovlar tugashini kutadi. 10 soniya o‘tsa ham tugamasa, xato qaytaradi.Shutdownchaqirilgach, goroutine ichidagiListenAndServehttp.ErrServerClosedqaytaradi. Bu xato emas, shuning uchunerrors.Isbilan alohida tekshiriladi.
Info
SIGTERM — Docker, Kubernetes va systemd konteyner yoki servisni to‘xtatayotganda yuboradigan signal. Server shu signalga to‘g‘ri javob bersa, yangi versiyani chiqarish (deploy) paytida foydalanuvchi so‘rovlari uzilmaydi.
Xulosa
Bu darsda quyidagilarni o‘rgandik:
http.HandleFunchandlerniDefaultServeMuxga qo‘shadi,http.Handleesa tayyorhttp.Handlerobyektini qabul qiladi;- bir pattern ikki marta qo‘shilsa, dastur
panicbilan to‘xtaydi; http.ListenAndServebloklovchi va doim xato qaytaradi, shuning uchun natijasini tekshirish kerak;- har bir so‘rov alohida goroutine’da ishlaydi, umumiy ma’lumotni himoyalash lozim;
- production’da
http.Servertimeoutlar bilan yaratiladi vaShutdownorqali tartib bilan to‘xtatiladi.
Keyingi darsda handlerning ikki argumenti — http.ResponseWriter va *http.Request bilan yaqindan tanishamiz.