The Basic CRUD Handlers: Create & Read
Asosiy CRUD handlerlar: Yaratish va O'qish
Kutubxona kartotekasini tasavvur qiling: yangi kitob kelganda, kutubxonachi UNGA yangi KARTOCHKA yozadi va katalogga qo'shadi (Create) — mijoz esa kartochka raqamini aytib, o'sha kitob haqida ma'lumot so'raydi (Read). Bizning Bookstore API'da ham xuddi shu ikki amal — POST /books (yaratish) va GET /books/{id} (o'qish) — birinchi ishlaydigan qismlar bo'ladi.
package main
import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"strconv"
"strings"
"sync"
)
type Book struct {
ID string `json:"id"`
Title string `json:"title"`
Author string `json:"author"`
Price float64 `json:"price"`
}
type BookStore struct {
mu sync.Mutex
books map[string]*Book
nextID int
}
func NewBookStore() *BookStore {
return &BookStore{books: make(map[string]*Book)}
}
func (s *BookStore) Create(title, author string, price float64) *Book {
s.mu.Lock()
defer s.mu.Unlock()
s.nextID++
id := strconv.Itoa(s.nextID)
book := &Book{ID: id, Title: title, Author: author, Price: price}
s.books[id] = book
return book
}
func (s *BookStore) Get(id string) (*Book, bool) {
s.mu.Lock()
defer s.mu.Unlock()
book, ok := s.books[id]
return book, ok
}
func main() {
store := NewBookStore()
mux := http.NewServeMux()
mux.HandleFunc("POST /books", func(w http.ResponseWriter, r *http.Request) {
var req struct {
Title string `json:"title"`
Author string `json:"author"`
Price float64 `json:"price"`
}
json.NewDecoder(r.Body).Decode(&req)
book := store.Create(req.Title, req.Author, req.Price)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(book)
})
mux.HandleFunc("GET /books/{id}", func(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
book, ok := store.Get(id)
if !ok {
w.WriteHeader(http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(book)
})
createBody := strings.NewReader(`{"title":"Go bilan tanishuv","author":"A. Karimov","price":45000}`)
createReq := httptest.NewRequest("POST", "/books", createBody)
createRec := httptest.NewRecorder()
mux.ServeHTTP(createRec, createReq)
fmt.Println("POST /books ->", createRec.Code)
getReq := httptest.NewRequest("GET", "/books/1", nil)
getRec := httptest.NewRecorder()
mux.ServeHTTP(getRec, getReq)
fmt.Println("GET /books/1 ->", getRec.Code)
fmt.Println(getRec.Body.String())
}http.NewServeMux() va "POST /books", "GET /books/{id}" shablonlari — "Routing and Path Parameters" darsida ko'rgan METOD+YO'L naqshi: bitta mux ICHIDA, har bir (metod, yo'l) juftligi O'ZINING handler'iga ega. BookStore — sync.Mutex bilan himoyalangan, chunki HAQIQIY serverda ko'plab so'rovlar BIR VAQTDA kelishi mumkin ("Mutex" darsidagi tamoyil): ikkita so'rov bir vaqtda nextIDni oshirsa, mu.Lock()/Unlock() ular BIR-BIRINI KUTISHINI ta'minlaydi.
httptest.NewRequest + httptest.NewRecorder + mux.ServeHTTP(rec, req) — "HTTP Testing with httptest" darsida ko'rgan naqsh: HAQIQIY tarmoq portini ochmasdan, handler'ni to'g'ridan-to'g'ri chaqirib sinaymiz. json.NewEncoder(w).Encode(book) — Book struct'ini JAVOB TANASIGA to'g'ridan-to'g'ri JSON qilib yozadi; maydonlar JSON'da ANIQ struct'da yozilgan TARTIBDA chiqadi (id, title, author, price), shuning uchun natija har doim BASHORAT QILINADIGAN.
>_ Exercise
BookStore'ga barcha kitoblarni RO'YXAT qilib qaytaruvchi endpoint qo'shing.
- •BookStore'ga List() []*Book metodini qo'shing: barcha kitoblarni ID bo'yicha SONLI tartibda (sort.Slice va strconv.Atoi bilan) saralab qaytaring — xarita tartibi TASODIFIY bo'lgani uchun ("Iterating over Maps" darsini eslang)
- •"GET /books" handlerini yozing: store.List() natijasini JSON massiv sifatida javob tanasiga yozing
- •ikkita kitob yaratib (store.Create orqali), GET /books ga so'rov yuboring va javob tanasini chop eting
Stuck? Reveal a hint to help you.
Key Takeaway
Key Takeaway:
Create (POST) va Read (GET) — CRUD'ning birinchi ikki amali; ro'yxat qaytarishda xarita tartibi TASODIFIY bo'lgani uchun, natijani har doim ANIQ bir mezon (masalan ID) bo'yicha saralash kerak.
NEXT UP
The Basic CRUD Handlers: Update & Delete
$ go run main.go
Kodingizni ishga tushiring