GoDasturchi
Partial Updates with PATCH

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.

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

Hints (0/3)

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

OUTPUT

$ go run main.go
Kodingizni ishga tushiring

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.

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

Hints (0/3)

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