GoDasturchi
Validation: Custom Rules & Error Messages

Validation: Custom Rules & Error Messages

Validatsiya: Maxsus qoidalar va xato xabarlari

Shifokorning qabulida hamma tekshiruv (harorat, bosim, puls) BIR VAQTDA o'tkaziladi va bemorga BARCHA muammo BIRDANIGA aytiladi — shifokor "avval haroratni tuzataylik, keyin qaytib keling bosimni aytaman" demaydi. Oldingi darsdagi validate funksiyamiz esa aynan shunday ishlar edi: FAQAT BIRINCHI xatoni qaytarardi. Foydalanuvchi uchun bu — har safar BITTA xatoni tuzatib, QAYTA yuborib, KEYINGI xatoni bilish degani. Yaxshi API esa BARCHA xatoni BIR SO'ROVDA qaytaradi.

example.go
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"strings"
)

type CreateBookRequest struct {
	Title  string  `json:"title"`
	Author string  `json:"author"`
	Price  float64 `json:"price"`
}

// FieldError — bitta maydon bo'yicha bitta xato
type FieldError struct {
	Field   string `json:"field"`
	Message string `json:"message"`
}

func validateBook(req CreateBookRequest) []FieldError {
	var errs []FieldError
	if strings.TrimSpace(req.Title) == "" {
		errs = append(errs, FieldError{Field: "title", Message: "bo'sh bo'lishi mumkin emas"})
	}
	if strings.TrimSpace(req.Author) == "" {
		errs = append(errs, FieldError{Field: "author", Message: "bo'sh bo'lishi mumkin emas"})
	}
	if req.Price <= 0 {
		errs = append(errs, FieldError{Field: "price", Message: "musbat son bo'lishi kerak"})
	}
	// maxsus (custom) qoida: narx haddan tashqari yuqori bo'lsa ham xato
	if req.Price > 5000000 {
		errs = append(errs, FieldError{Field: "price", Message: "juda yuqori narx"})
	}
	return errs
}

func createHandler(w http.ResponseWriter, r *http.Request) {
	var req CreateBookRequest
	json.NewDecoder(r.Body).Decode(&req)

	if errs := validateBook(req); len(errs) > 0 {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusUnprocessableEntity)
		json.NewEncoder(w).Encode(errs)
		return
	}

	w.WriteHeader(http.StatusCreated)
	fmt.Fprint(w, "yaratildi")
}

func main() {
	req := httptest.NewRequest("POST", "/books", strings.NewReader(`{"price":0}`))
	rec := httptest.NewRecorder()
	createHandler(rec, req)
	fmt.Println(rec.Code)
	fmt.Print(rec.Body.String())
}

var errs []FieldError — BO'SH (nil) slice bilan boshlanadi, har bir topilgan xato append bilan QO'SHIB boriladi. Bu — validatsiyada JUDA muhim naqsh: returnbilan DARHOL chiqib ketmaymiz, BALKI barcha tekshiruvni OXIRIGACHA yurib chiqamiz, keyin YIG'ILGAN natijani qaytaramiz. len(errs) > 0 — hech bo'lmasa BITTA xato bo'lsa, BUTUN ro'yxatni JSON massiv sifatida qaytaradi.

Diqqat qiling: price maydoni IKKI XIL sababdan xato bo'lishi mumkin (0/manfiy YOKI juda yuqori) — bitta maydon bo'yicha bir nechta "maxsus qoida" (custom rule) bo'lishi ODATIY holat, va HAR BIRI o'z FieldError yozuvini qo'shishi mumkin.

>_ Exercise

Sarlavha uzunligiga maxsus qoida qo'shing.

  • validateBook ichida yangi qoida qo'shing: agar len(req.Title) > 200 bo'lsa, FieldError{Field: "title", Message: "200 belgidan oshmasligi kerak"} qo'shing
  • bo'sh price BILAN BIRGA 200 belgidan uzun title yuborilgan so'rovni sinab ko'ring — ikkala xato ham qaytishi kerak
  • natija sifatida status kodni va javob tanasini chop eting

Stuck? Reveal a hint to help you.

Hints (0/3)

Key Takeaway

Key Takeaway:

Maxsus validatsiya qoidalari (custom rules) — oddiy "bo'shmi?" tekshiruvidan tashqari, biznesga xos chegaralarni (uzunlik, narx oralig'i) ifodalaydi; barcha xatolarni BIR so'rovda YIG'IB qaytarish — foydalanuvchi tajribasini SEZILARLI yaxshilaydi.

NEXT UP

Structured Error Responses

OUTPUT

$ go run main.go
Kodingizni ishga tushiring

Validation: Custom Rules & Error Messages

Validatsiya: Maxsus qoidalar va xato xabarlari

Shifokorning qabulida hamma tekshiruv (harorat, bosim, puls) BIR VAQTDA o'tkaziladi va bemorga BARCHA muammo BIRDANIGA aytiladi — shifokor "avval haroratni tuzataylik, keyin qaytib keling bosimni aytaman" demaydi. Oldingi darsdagi validate funksiyamiz esa aynan shunday ishlar edi: FAQAT BIRINCHI xatoni qaytarardi. Foydalanuvchi uchun bu — har safar BITTA xatoni tuzatib, QAYTA yuborib, KEYINGI xatoni bilish degani. Yaxshi API esa BARCHA xatoni BIR SO'ROVDA qaytaradi.

example.go
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"strings"
)

type CreateBookRequest struct {
	Title  string  `json:"title"`
	Author string  `json:"author"`
	Price  float64 `json:"price"`
}

// FieldError — bitta maydon bo'yicha bitta xato
type FieldError struct {
	Field   string `json:"field"`
	Message string `json:"message"`
}

func validateBook(req CreateBookRequest) []FieldError {
	var errs []FieldError
	if strings.TrimSpace(req.Title) == "" {
		errs = append(errs, FieldError{Field: "title", Message: "bo'sh bo'lishi mumkin emas"})
	}
	if strings.TrimSpace(req.Author) == "" {
		errs = append(errs, FieldError{Field: "author", Message: "bo'sh bo'lishi mumkin emas"})
	}
	if req.Price <= 0 {
		errs = append(errs, FieldError{Field: "price", Message: "musbat son bo'lishi kerak"})
	}
	// maxsus (custom) qoida: narx haddan tashqari yuqori bo'lsa ham xato
	if req.Price > 5000000 {
		errs = append(errs, FieldError{Field: "price", Message: "juda yuqori narx"})
	}
	return errs
}

func createHandler(w http.ResponseWriter, r *http.Request) {
	var req CreateBookRequest
	json.NewDecoder(r.Body).Decode(&req)

	if errs := validateBook(req); len(errs) > 0 {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusUnprocessableEntity)
		json.NewEncoder(w).Encode(errs)
		return
	}

	w.WriteHeader(http.StatusCreated)
	fmt.Fprint(w, "yaratildi")
}

func main() {
	req := httptest.NewRequest("POST", "/books", strings.NewReader(`{"price":0}`))
	rec := httptest.NewRecorder()
	createHandler(rec, req)
	fmt.Println(rec.Code)
	fmt.Print(rec.Body.String())
}

var errs []FieldError — BO'SH (nil) slice bilan boshlanadi, har bir topilgan xato append bilan QO'SHIB boriladi. Bu — validatsiyada JUDA muhim naqsh: returnbilan DARHOL chiqib ketmaymiz, BALKI barcha tekshiruvni OXIRIGACHA yurib chiqamiz, keyin YIG'ILGAN natijani qaytaramiz. len(errs) > 0 — hech bo'lmasa BITTA xato bo'lsa, BUTUN ro'yxatni JSON massiv sifatida qaytaradi.

Diqqat qiling: price maydoni IKKI XIL sababdan xato bo'lishi mumkin (0/manfiy YOKI juda yuqori) — bitta maydon bo'yicha bir nechta "maxsus qoida" (custom rule) bo'lishi ODATIY holat, va HAR BIRI o'z FieldError yozuvini qo'shishi mumkin.

>_ Exercise

Sarlavha uzunligiga maxsus qoida qo'shing.

  • validateBook ichida yangi qoida qo'shing: agar len(req.Title) > 200 bo'lsa, FieldError{Field: "title", Message: "200 belgidan oshmasligi kerak"} qo'shing
  • bo'sh price BILAN BIRGA 200 belgidan uzun title yuborilgan so'rovni sinab ko'ring — ikkala xato ham qaytishi kerak
  • natija sifatida status kodni va javob tanasini chop eting

Stuck? Reveal a hint to help you.

Hints (0/3)

Key Takeaway

Key Takeaway:

Maxsus validatsiya qoidalari (custom rules) — oddiy "bo'shmi?" tekshiruvidan tashqari, biznesga xos chegaralarni (uzunlik, narx oralig'i) ifodalaydi; barcha xatolarni BIR so'rovda YIG'IB qaytarish — foydalanuvchi tajribasini SEZILARLI yaxshilaydi.

NEXT UP

Structured Error Responses