Partial Updates with PATCH
PATCH bilan qisman yangilash
Bank hisobingizdagi FAQAT telefon raqamini yangilashni xohlaysiz — pasport, manzil, ismingizni QAYTA yozib yuborishga hojat yo'q. "Update & Delete" darsidagi PUT esa xuddi "BUTUN blanka'ni QAYTA to'ldirish" edi: yuborilmagan maydon BO'SH bo'lib QOLARDI. PATCH — FAQAT o'zgartirmoqchi bo'lgan maydonlarni YUBORISH imkonini beradi, qolganlari TEGILMAY qoladi.
package main
import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"strings"
"sync"
)
type Book struct {
ID string `json:"id"`
Title string `json:"title"`
Author string `json:"author"`
Price float64 `json:"price"`
}
// PatchBookRequest — POINTER maydonlar: nil bo'lsa "yuborilmagan", qiymat bo'lsa "yangilash kerak"
type PatchBookRequest struct {
Title *string `json:"title"`
Author *string `json:"author"`
Price *float64 `json:"price"`
}
type BookStore struct {
mu sync.Mutex
books map[string]*Book
}
func NewBookStore() *BookStore { return &BookStore{books: make(map[string]*Book)} }
func (s *BookStore) Patch(id string, req PatchBookRequest) (*Book, bool) {
s.mu.Lock()
defer s.mu.Unlock()
book, ok := s.books[id]
if !ok {
return nil, false
}
if req.Title != nil {
book.Title = *req.Title
}
if req.Author != nil {
book.Author = *req.Author
}
if req.Price != nil {
book.Price = *req.Price
}
return book, true
}
func main() {
store := NewBookStore()
store.books["1"] = &Book{ID: "1", Title: "Go bilan tanishuv", Author: "A. Karimov", Price: 45000}
mux := http.NewServeMux()
mux.HandleFunc("PATCH /books/{id}", func(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
var req PatchBookRequest
json.NewDecoder(r.Body).Decode(&req)
book, ok := store.Patch(id, req)
if !ok {
w.WriteHeader(http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(book)
})
req := httptest.NewRequest("PATCH", "/books/1", strings.NewReader(`{"price":49000}`))
rec := httptest.NewRecorder()
mux.ServeHTTP(rec, req)
fmt.Print(rec.Body.String())
}*string, *float64 — POINTER turlar ("Pointers" darsini eslang): oddiy string maydon HECH QACHON "yuborilmadi" bilan "bo'sh matn yuborildi"ni FARQLAY OLMAYDI (ikkalasi ham ""). Pointer esa BUNI hal qiladi: nil — "bu maydon so'rovda UMUMAN yo'q edi", pointer bo'sh bo'lmagan qiymat bilan — "bu maydon ANIQ shu qiymatga o'zgartirilishi kerak".
Natijada: {"price":49000} so'rovi FAQAT Priceni o'zgartiradi — Title va Author O'ZGARISHSIZ qoladi. Bu — PUTdan tubdan FARQLI xulq-atvor: PUT bilan xuddi shu so'rov yuborilsa, Title va Author BO'SH matnga aylanib QOLARDI.
>_ Exercise
PATCH'ning ikkita muhim holatini sinang: qisman yangilash va mavjud bo'lmagan ID.
- •faqat title'ni o'zgartiruvchi so'rov yuboring (\
{"title":"Go bilan tanishuv (2-nashr)"}\) — author va price O'ZGARMASLIGINI natijadan ko'ring - •mavjud bo'lmagan "/books/999" ID'siga PATCH so'rovi yuboring
- •ikkala natijani (birinchi javob tanasi, ikkinchi status kodi) chop eting
Stuck? Reveal a hint to help you.
Key Takeaway
Key Takeaway:
PATCH — pointer maydonlar orqali "yuborilmagan" (nil) va "bo'sh qiymat yuborilgan" holatlarni farqlaydi, shu sabab FAQAT so'rovda ANIQ ko'rsatilgan maydonlarni yangilaydi; PUT esa har doim BUTUN resursni almashtiradi.
NEXT UP
Idempotency Keys
$ go run main.go
Kodingizni ishga tushiring