📋 Menu Nhà Hàng - Maps
Chào mừng đến với bài học về Maps - hệ thống menu và tra cứu giá trong Bếp Á!
🎯 Món Ăn Hôm Nay
Tưởng tượng bạn là quản lý nhà hàng với bảng giá:
- Phở Bò → 50,000 VND
- Bún Chả → 45,000 VND
- Gỏi Cuốn → 30,000 VND
Khách hỏi "Phở bao nhiêu?" → Bạn tra menu → Trả lời "50,000 VND"
Đó chính là Map - bảng tra cứu key-value!
🥘 Maps Là Gì?
Map = Menu nhà hàng (tra cứu món → giá)
// Menu: Tên món → Giá tiền
menu := map[string]int{
"Phở Bò": 50000,
"Bún Chả": 45000,
"Gỏi Cuốn": 30000,
}
// Tra cứu giá
gia := menu["Phở Bò"]
fmt.Println(gia) // 50000
🍜 Ẩn Dụ Nhà Hàng:
- Key (Tên món) = Món khách gọi
- Value (Giá) = Giá tiền phải trả
- map[key] = Tra menu
👨🍳 Câu Chuyện Trong Bếp
Sáng nay, quán phở của anh Hùng đông khách:
Tình huống 1: Khách hỏi giá
menu := map[string]int{
"Phở Bò": 50000,
"Phở Gà": 45000,
"Bún Chả": 45000,
}
// Khách hỏi: "Phở Bò bao nhiêu?"
gia, coMon := menu["Phở Bò"]
if coMon {
fmt.Printf("Phở Bò: %d VND\n", gia)
} else {
fmt.Println("❌ Hết món rồi ạ!")
}
Tình huống 2: Cập nhật menu
// Thêm món mới
menu["Nem Rán"] = 25000
// Tăng giá do nguyên liệu đắt
menu["Phở Bò"] = 55000
// Xóa món hết nguyên liệu
delete(menu, "Bún Chả")
🎉 Kết quả: Map giúp quản lý menu dễ dàng!
📝 Công Thức Nấu (Code Examples)
Ví Dụ 1: Tạo Menu Cơ Bản
package main
import "fmt"
func main() {
// Cách 1: Tạo menu trống
menu := make(map[string]int)
menu["Phở Bò"] = 50000
menu["Bún Chả"] = 45000
// Cách 2: Tạo menu có sẵn món
menuDayDu := map[string]int{
"Phở Bò": 50000,
"Phở Gà": 45000,
"Bún Chả": 45000,
"Gỏi Cuốn": 30000,
"Nem Rán": 25000,
}
fmt.Println("📋 MENU NHÀ HÀNG:")
for mon, gia := range menuDayDu {
fmt.Printf("%-15s: %d VND\n", mon, gia)
}
}
Ví Dụ 2: Tra Cứu An Toàn
func main() {
menu := map[string]int{
"Phở Bò": 50000,
"Bún Chả": 45000,
}
// Khách gọi món
monKhachGoi := "Cơm Tấm"
// Tra menu an toàn
gia, coMon := menu[monKhachGoi]
if coMon {
fmt.Printf("✅ %s: %d VND\n", monKhachGoi, gia)
} else {
fmt.Printf("❌ Xin lỗi, không có %s\n", monKhachGoi)
fmt.Println("\n📋 Menu hiện có:")
for mon := range menu {
fmt.Println("- " + mon)
}
}
}
Ví Dụ 3: Map Với Struct - Thông Tin Chi Tiết
type MonAn struct {
Ten string
Gia int
ThoiGianNau int // phút
NguyenLieu []string
}
func main() {
menu := map[string]MonAn{
"PHO_BO": {
Ten: "Phở Bò",
Gia: 50000,
ThoiGianNau: 10,
NguyenLieu: []string{"Thịt bò", "Bánh phở", "Nước dùng"},
},
"BUN_CHA": {
Ten: "Bún Chả",
Gia: 45000,
ThoiGianNau: 15,
NguyenLieu: []string{"Thịt nướng", "Bún", "Nước mắm"},
},
}
// In thông tin món
mon := menu["PHO_BO"]
fmt.Printf("🍜 %s\n", mon.Ten)
fmt.Printf("💰 Giá: %d VND\n", mon.Gia)
fmt.Printf("⏱️ Thời gian: %d phút\n", mon.ThoiGianNau)
fmt.Println("🥘 Nguyên liệu:")
for _, nl := range mon.NguyenLieu {
fmt.Println(" - " + nl)
}
}
Ví Dụ 4: Đếm Món Đã Bán
func main() {
// Thống kê món đã bán
daBan := map[string]int{}
// Khách gọi món (giả lập)
orderList := []string{"Phở Bò", "Bún Chả", "Phở Bò", "Gỏi Cuốn", "Phở Bò"}
for _, mon := range orderList {
daBan[mon]++ // Tăng số lượng
}
fmt.Println("📊 THỐNG KÊ MÓN ĐÃ BÁN:")
for mon, soLuong := range daBan {
fmt.Printf("%-15s: %d tô/phần\n", mon, soLuong)
}
}
Ví Dụ 5: Map Lồng Nhau - Menu Theo Loại
func main() {
menuTheoLoai := map[string]map[string]int{
"Món chính": {
"Phở Bò": 50000,
"Bún Chả": 45000,
"Cơm Tấm": 40000,
},
"Món phụ": {
"Gỏi Cuốn": 30000,
"Nem Rán": 25000,
"Chả Giò": 28000,
},
"Nước uống": {
"Trà Đá": 5000,
"Nước Chanh": 15000,
"Sinh Tố": 25000,
},
}
fmt.Println("📋 MENU THEO LOẠI:\n")
for loai, danhSach := range menuTheoLoai {
fmt.Printf("=== %s ===\n", loai)
for mon, gia := range danhSach {
fmt.Printf("%-15s: %d VND\n", mon, gia)
}
fmt.Println()
}
}
🔥 Thực Hành Trong Bếp
Bài Tập 1: Hệ Thống Đặt Món
package main
import "fmt"
func main() {
menu := map[string]int{
"Phở Bò": 50000,
"Bún Chả": 45000,
"Gỏi Cuốn": 30000,
}
// Đơn hàng khách
donHang := map[string]int{
"Phở Bò": 2,
"Gỏi Cuốn": 3,
}
fmt.Println("🧾 HÓA ĐƠN:\n")
tongTien := 0
for mon, soLuong := range donHang {
gia := menu[mon]
thanhTien := gia * soLuong
tongTien += thanhTien
fmt.Printf("%-15s x%d = %d VND\n", mon, soLuong, thanhTien)
}
fmt.Println("━━━━━━━━━━━━━━━━━━━━━━━━━━")
fmt.Printf("TỔNG CỘNG: %d VND\n", tongTien)
}
Bài Tập 2: Giảm Giá Theo Khách Hàng
func main() {
menu := map[string]int{
"Phở Bò": 50000,
"Bún Chả": 45000,
}
// Mức giảm giá theo loại khách
giamGia := map[string]int{
"VIP": 20, // 20%
"ThanhVien": 10, // 10%
"ThuongXuyen": 5, // 5%
}
loaiKhach := "VIP"
mon := "Phở Bò"
giaGoc := menu[mon]
phanTramGiam := giamGia[loaiKhach]
soTienGiam := giaGoc * phanTramGiam / 100
giaSauGiam := giaGoc - soTienGiam
fmt.Printf("🍜 Món: %s\n", mon)
fmt.Printf("👤 Loại khách: %s\n", loaiKhach)
fmt.Printf("💵 Giá gốc: %d VND\n", giaGoc)
fmt.Printf("🎉 Giảm %d%%: -%d VND\n", phanTramGiam, soTienGiam)
fmt.Printf("💰 Thanh toán: %d VND\n", giaSauGiam)
}
Bài Tập 3: Quản Lý Tồn Kho
func main() {
// Số lượng tồn kho
tonKho := map[string]int{
"Phở Bò": 20,
"Bún Chả": 15,
"Gỏi Cuốn": 30,
}
// Khách đặt món
monDat := "Phở Bò"
soLuongDat := 5
fmt.Printf("📦 Tồn kho %s: %d phần\n", monDat, tonKho[monDat])
fmt.Printf("🛒 Khách đặt: %d phần\n", soLuongDat)
if tonKho[monDat] >= soLuongDat {
tonKho[monDat] -= soLuongDat
fmt.Printf("✅ Đặt thành công!\n")
fmt.Printf("📦 Còn lại: %d phần\n", tonKho[monDat])
} else {
fmt.Printf("❌ Không đủ hàng!\n")
fmt.Printf("📦 Chỉ còn: %d phần\n", tonKho[monDat])
}
}
⚠️ Những Lỗi Đầu Bếp Thường Gặp
Lỗi 1: Map Chưa Khởi Tạo
// ❌ SAI: Map nil không thể gán
func main() {
var menu map[string]int
menu["Phở"] = 50000 // Panic!
}
// ✅ ĐÚNG: Khởi tạo trước khi dùng
func main() {
menu := make(map[string]int)
menu["Phở"] = 50000 // OK
}
Lỗi 2: Không Kiểm Tra Key Tồn Tại
// ❌ SAI: Không biết món có hay không
func main() {
menu := map[string]int{"Phở": 50000}
gia := menu["Bún"]
fmt.Println(gia) // 0 - Không biết có món hay không
}
// ✅ ĐÚNG: Kiểm tra trước khi dùng
func main() {
menu := map[string]int{"Phở": 50000}
if gia, ok := menu["Bún"]; ok {
fmt.Println(gia)
} else {
fmt.Println("❌ Không có món này!")
}
}
Lỗi 3: Map Không Giữ Thứ Tự
// ❌ SAI: Mong đợi thứ tự cố định
func main() {
menu := map[string]int{
"Phở": 50000,
"Bún": 45000,
"Gỏi": 30000,
}
// Thứ tự in ra ngẫu nhiên mỗi lần chạy!
for mon := range menu {
fmt.Println(mon)
}
}
// ✅ ĐÚNG: Dùng slice để giữ thứ tự
func main() {
menu := map[string]int{
"Phở": 50000,
"Bún": 45000,
"Gỏi": 30000,
}
// Danh sách thứ tự
thuTu := []string{"Phở", "Bún", "Gỏi"}
for _, mon := range thuTu {
fmt.Printf("%s: %d VND\n", mon, menu[mon])
}
}
Lỗi 4: Thay Đổi Map Khi Duyệt
// ❌ SAI: Thay đổi map khi đang duyệt
func main() {
menu := map[string]int{"Phở": 50000}
for mon := range menu {
delete(menu, mon) // Nguy hiểm!
menu["Bún"] = 45000 // Có thể lỗi!
}
}
// ✅ ĐÚNG: Lưu keys trước, rồi mới thay đổi
func main() {
menu := map[string]int{"Phở": 50000}
keys := []string{}
for mon := range menu {
keys = append(keys, mon)
}
for _, mon := range keys {
delete(menu, mon)
}
menu["Bún"] = 45000 // An toàn
}
💡 Bí Quyết Của Đầu Bếp
- Luôn khởi tạo map: Dùng
make()hoặcmap[K]V{} - Kiểm tra key tồn tại: Dùng
value, ok := map[key] - Map không có thứ tự: Dùng slice riêng nếu cần thứ tự
- Capacity cho map lớn:
make(map[K]V, size)khi biết trước - Tránh thay đổi khi duyệt: Lưu keys ra riêng trước
🎓 Bạn Đã Học Được
- ✅ Map = Bảng tra cứu key → value (Menu → Giá)
- ✅ make() = Tạo map mới
- ✅ map[key] = value = Thêm/sửa phần tử
- ✅ value, ok := map[key] = Tra cứu an toàn
- ✅ delete(map, key) = Xóa phần tử
- ✅ for key, value := range map = Duyệt map
🍜 Món Tiếp Theo
Menu đã có! Giờ cần đơn gọi món cho khách:
💡 Lời Khuyên Cuối: Map giống menu nhà hàng - càng rõ ràng, càng tra nhanh! Thực hành nhiều với map để quản lý dữ liệu hiệu quả như đầu bếp chuyên nghiệp!