package main import ( "encoding/json" "fmt" "html/template" "log" "net/http" "strconv" "sync" ) type Product struct { ID int `json:"id"` Name string `json:"name"` Price float64 `json:"price"` } var ( products []Product mu sync.Mutex // Для безопасного доступа к списку продуктов nextID int = 1 // Для автоматической генерации ID ) // Структура для передачи данных в шаблон type PageData struct { Products []Product Cart []CartItem } type CartItem struct { ProductID int `json:"product_id"` UserID int `json:"user_id"` Quantity int `json:"quantity"` CreatedID int `json:"created_id"` } // Получение корзины из cookies func GetCartFromCookie(r *http.Request) ([]CartItem, error) { // Read the cookie cookie, err := r.Cookie("cart") if err != nil { if err == http.ErrNoCookie { // If no cookie, return an empty cart return []CartItem{}, nil } return nil, fmt.Errorf("failed to read cart cookie: %w", err) } // Check if the cookie value looks like JSON var cart []CartItem err = json.Unmarshal([]byte(cookie.Value), &cart) if err != nil { log.Println("Invalid cart cookie value, resetting cart.") return []CartItem{}, nil // Reset to an empty cart on error } return cart, nil } // Сохранение корзины в cookies func SetCartCookie(w http.ResponseWriter, cart []CartItem) error { cartJSON, err := json.Marshal(cart) if err != nil { return fmt.Errorf("failed to serialize cart: %w", err) } // Устанавливаем cookie с корзиной http.SetCookie(w, &http.Cookie{ Name: "cart", Value: string(cartJSON), Path: "/", }) return nil } func renderTemplate(w http.ResponseWriter, r *http.Request, cart []CartItem) { tmpl, err := template.New("index").Parse(` Products

Products

{{range .Products}} {{end}}
Product ID Name Price Action
{{.ID}} {{.Name}} {{.Price}} Edit | Delete

Add a New Product





Cart

{{range .Cart}} {{end}}
Product ID Quantity
{{.ProductID}} {{.Quantity}}
`) if err != nil { log.Println("Error parsing template:", err) http.Error(w, "Error parsing template", http.StatusInternalServerError) return } // Передаем данные продукта и корзины в шаблон data := PageData{ Products: products, Cart: cart, } err = tmpl.Execute(w, data) if err != nil { log.Println("Error executing template:", err) http.Error(w, "Error executing template", http.StatusInternalServerError) return } } func AddProduct(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodPost { // Получаем данные из формы name := r.FormValue("name") price := r.FormValue("price") // Преобразуем цену в float var priceFloat float64 _, err := fmt.Sscanf(price, "%f", &priceFloat) if err != nil { http.Error(w, "Invalid price", http.StatusBadRequest) return } // Создаем новый продукт mu.Lock() product := Product{ ID: nextID, Name: name, Price: priceFloat, } nextID++ products = append(products, product) mu.Unlock() // Перенаправляем пользователя на главную страницу после добавления продукта http.Redirect(w, r, "/", http.StatusFound) return } // Получаем корзину из cookies cart, err := GetCartFromCookie(r) if err != nil { http.Error(w, fmt.Sprintf("Error reading cart: %v", err), http.StatusInternalServerError) return } // Отображаем шаблон с обновленным списком продуктов и корзиной renderTemplate(w, r, cart) } func EditProduct(w http.ResponseWriter, r *http.Request) { idStr := r.URL.Path[len("/edit/"):] id, err := strconv.Atoi(idStr) if err != nil { http.Error(w, "Invalid product ID", http.StatusBadRequest) return } // Ищем продукт по ID var product *Product for i := range products { if products[i].ID == id { product = &products[i] break } } if product == nil { http.Error(w, "Product not found", http.StatusNotFound) return } if r.Method == http.MethodPost { // Обновляем детали продукта product.Name = r.FormValue("name") price := r.FormValue("price") var priceFloat float64 _, err := fmt.Sscanf(price, "%f", &priceFloat) if err != nil { http.Error(w, "Invalid price", http.StatusBadRequest) return } product.Price = priceFloat // Перенаправляем на главную страницу http.Redirect(w, r, "/", http.StatusFound) return } // Получаем корзину из cookies // cart, err := GetCartFromCookie(r) // if err != nil { // http.Error(w, fmt.Sprintf("Error reading cart: %v", err), http.StatusInternalServerError) // return // } // Отображаем форму редактирования продукта tmpl := `

Edit Product





` tmplParsed, err := template.New("edit").Parse(tmpl) if err != nil { http.Error(w, "Error parsing template", http.StatusInternalServerError) return } // Передаем данные продукта в шаблон tmplParsed.Execute(w, product) } func DeleteProduct(w http.ResponseWriter, r *http.Request) { idStr := r.URL.Path[len("/delete/"):] id, err := strconv.Atoi(idStr) if err != nil { http.Error(w, "Invalid product ID", http.StatusBadRequest) return } // Находим индекс продукта для удаления mu.Lock() defer mu.Unlock() for i, product := range products { if product.ID == id { // Удаляем продукт из списка products = append(products[:i], products[i+1:]...) break } } // Получаем корзину из cookies cart, err := GetCartFromCookie(r) if err != nil { http.Error(w, fmt.Sprintf("Error reading cart: %v", err), http.StatusInternalServerError) return } // Сохраняем обновленную корзину в cookies (если необходимо) err = SetCartCookie(w, cart) if err != nil { http.Error(w, fmt.Sprintf("Error setting cart cookie: %v", err), http.StatusInternalServerError) return } // Перенаправляем на главную страницу http.Redirect(w, r, "/", http.StatusFound) } func main() { // Обработчики маршрутов http.HandleFunc("/add", AddProduct) http.HandleFunc("/edit/", EditProduct) http.HandleFunc("/delete/", DeleteProduct) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { // Получаем корзину из cookies cart, err := GetCartFromCookie(r) if err != nil { http.Error(w, fmt.Sprintf("Error reading cart: %v", err), http.StatusInternalServerError) return } // Отображаем шаблон с корзиной renderTemplate(w, r, cart) }) log.Println("Server is running on http://localhost:8080") log.Fatal(http.ListenAndServe(":8080", nil)) }