🗂️ Sắp Xếp Bếp - Code Organization
Chào mừng bạn đến bài học về tổ chức code - cách sắp xếp bếp để nấu ăn hiệu quả!
🎯 Món Ăn Hôm Nay
Tưởng tượng một nhà hàng lớn với nhiều khu vực:
- Khu sơ chế: Rửa rau, thái thịt (packages cơ bản)
- Khu chiên xào: Nấu món chính (main package)
- Khu kho: Lưu trữ nguyên liệu (external packages)
Đó chính là cách tổ chức code trong Go!
🥘 Code Organization Là Gì?
Code Organization = Sắp xếp các khu vực trong bếp
Trong Go, chúng ta chia code thành:
- Packages: Các khu vực bếp khác nhau
- Folders: Kệ đựng đồ trong mỗi khu
- main package: Bếp chính - nơi tạo ra món ăn cuối cùng
- Import: Mượn dụng cụ/nguyên liệu từ khu khác
package main // Bep chinh
import (
"fmt" // Muon bat dua tu kho
"myrestaurant/soche" // Lay nguyen lieu tu khu so che
)
func main() {
fmt.Println("Nha hang dang hoat dong!")
}
👨🍳 Câu Chuyện Trong Bếp
Hôm nay, Chef Minh mở nhà hàng mới. Anh nhận ra:
Vấn đề: Nếu để tất cả nguyên liệu, dụng cụ chung một chỗ → lộn xộn, khó tìm!
Giải pháp: Chia bếp thành nhiều khu vực:
- Khu A: Sơ chế rau củ
- Khu B: Chế biến thịt cá
- Khu C: Nấu món chính
- Kho: Lưu trữ nguyên liệu
Mỗi khu có công việc riêng, nhưng làm việc cùng nhau tạo nên món ăn hoàn chỉnh!
Đó chính là code organization - chia nhỏ để dễ quản lý.
📝 Công Thức Nấu (Code)
Ví Dụ 1: Cấu Trúc Bếp Đơn Giản
myrestaurant/
├── main.go # Bep chinh - noi tao ra mon an
├── go.mod # Danh sach nguyen lieu can thiet
└── menu/
└── pho.go # Cong thuc nau pho
File: main.go
package main
import (
"fmt"
"myrestaurant/menu"
)
func main() {
// Bep chinh goi mon pho tu khu menu
pho := menu.NauPho()
fmt.Println(pho)
}
File: menu/pho.go
package menu
// NauPho la cong thuc nau pho o khu menu
func NauPho() string {
// Cac buoc nau pho
nuocDung := "nuoc xuong"
banhPho := "banh pho tuoi"
thit := "thit bo"
return "Pho bo voi " + nuocDung + ", " + banhPho + ", " + thit
}
🔍 Giải Thích:
package main: Bếp chính - điểm bắt đầu của nhà hàngpackage menu: Khu chuyên về menu món ănimport "myrestaurant/menu": Mượn công thức từ khu menu- Hàm bắt đầu bằng chữ hoa (NauPho) → public (đầu bếp khác dùng được)
- Hàm bắt đầu bằng chữ thường → private (chỉ trong bếp này dùng)
Ví Dụ 2: Cấu Trúc Bếp Đầy Đủ
myrestaurant/
├── main.go # Bep chinh
├── go.mod
├── menu/ # Khu menu
│ ├── pho.go
│ └── bun.go
├── soche/ # Khu so che
│ ├── rau.go
│ └── thit.go
└── kho/ # Kho luu tru
└── nguyenlieu.go
File: soche/rau.go
package soche
// RuaRau - ham public (chu hoa)
func RuaRau(tenRau string) string {
return "Da rua sach " + tenRau
}
// thaiRau - ham private (chu thuong)
func thaiRau(tenRau string) string {
return "Da thai " + tenRau
}
// ChuanBiRau - su dung ca 2 ham tren
func ChuanBiRau(tenRau string) string {
rauSach := RuaRau(tenRau)
rauThai := thaiRau(tenRau)
return rauSach + " va " + rauThai
}
File: main.go
package main
import (
"fmt"
"myrestaurant/soche"
"myrestaurant/menu"
)
func main() {
// Chuan bi nguyen lieu
rau := soche.ChuanBiRau("xa lach")
fmt.Println(rau)
// Nau mon
pho := menu.NauPho()
fmt.Println(pho)
// Loi! Ham private khong goi duoc
// soche.thaiRau("ca rot") // ❌ SAI - ham private
}
🔍 Giải Thích:
soche.ChuanBiRau(): Gọi hàm public từ package sochesoche.thaiRau(): KHÔNG thể gọi - hàm private (chữ thường)- Mỗi package có trách nhiệm riêng, dễ bảo trì
Ví Dụ 3: Sử Dụng Package Bên Ngoài
package main
import (
"fmt" // Package chuan cua Go
"time" // Package chuan ve thoi gian
"myrestaurant/menu" // Package cua minh
)
func main() {
// Lay gio hien tai
gio := time.Now().Hour()
if gio < 10 {
fmt.Println("Sang - phuc vu pho")
fmt.Println(menu.NauPho())
} else {
fmt.Println("Trua - phuc vu com")
}
}
🔍 Giải Thích:
- Package từ Go standard library:
fmt,time- Package tự viết:
myrestaurant/menu- Kết hợp linh hoạt để tạo chương trình hoàn chỉnh
🔥 Thực Hành Trong Bếp
Bài Tập 1: Tạo Package Đồ Uống
Tạo cấu trúc sau:
myrestaurant/
├── main.go
└── douong/
└── cafe.go
File: douong/cafe.go
package douong
// PhaCafe - pha ca phe
func PhaCafe(loai string) string {
return "Ca phe " + loai + " da san sang!"
}
// themDuong - them duong (private)
func themDuong(luong int) string {
return "Da them duong"
}
File: main.go
package main
import (
"fmt"
"myrestaurant/douong"
)
func main() {
cafe := douong.PhaCafe("den")
fmt.Println(cafe)
}
Nhiệm vụ: Chạy thử và quan sát kết quả!
Bài Tập 2: Thêm Package Tính Tiền
Tạo package thanhtoan với hàm TinhTien(tenMon string, soLuong int) int
Gợi ý:
package thanhtoan
// TinhTien - tinh tien mon an
func TinhTien(tenMon string, soLuong int) int {
bangGia := map[string]int{
"pho": 50000,
"bun": 40000,
"com": 35000,
}
gia := bangGia[tenMon]
return gia * soLuong
}
Sử dụng trong main.go để tính tiền 2 tô phở!
Bài Tập 3: Tổ Chức Bếp Hoàn Chỉnh
Tạo cấu trúc nhà hàng với:
- Package
menu: Chứa các món ăn (pho, bun, com) - Package
soche: Chuẩn bị nguyên liệu - Package
thanhtoan: Tính tiền main.go: Điều phối tất cả
Thử thách: Viết chương trình hoàn chỉnh từ đặt món → chuẩn bị → nấu → tính tiền!
⚠️ Những Lỗi Đầu Bếp Thường Gặp
Lỗi 1: Gọi Hàm Private Từ Package Khác
// File: menu/pho.go
package menu
func NauPho() string {
return "Pho bo"
}
func nauNuoc() string { // chu thuong = private
return "Nuoc xuong"
}
// File: main.go
package main
import "myrestaurant/menu"
func main() {
// ❌ SAI - ham private khong goi duoc
menu.nauNuoc() // Loi: undefined
// ✅ ĐÚNG - ham public goi duoc
menu.NauPho()
}
🔧 Cách sửa:
- Hàm public phải bắt đầu bằng chữ HOA
- Hàm private (chữ thường) chỉ dùng trong package đó
Lỗi 2: Package Name Không Khớp
// ❌ SAI
// File: menu/pho.go
package monchinh // Ten package khong khop voi ten thu muc
func NauPho() string {
return "Pho"
}
// ✅ ĐÚNG
// File: menu/pho.go
package menu // Ten package phai khop voi ten thu muc
func NauPho() string {
return "Pho"
}
🔧 Cách sửa: Tên package phải trùng với tên thư mục chứa nó
Lỗi 3: Import Sai Đường Dẫn
// ❌ SAI
import "menu" // Thieu ten module
// ✅ ĐÚNG
import "myrestaurant/menu" // Day du: module/package
🔧 Cách sửa:
- Luôn dùng đường dẫn đầy đủ:
module_name/package_name- Kiểm tra file
go.modđể biết tên module
Lỗi 4: Quên Tạo go.mod
# ❌ SAI - chua co go.mod
cd myrestaurant
go run main.go # Loi: cannot find package
# ✅ ĐÚNG
cd myrestaurant
go mod init myrestaurant # Tao go.mod
go run main.go
🔧 Cách sửa: Luôn chạy
go mod inittrước khi tạo packages
💡 Bí Quyết Của Đầu Bếp
-
Tên Package Ngắn Gọn:
- ✅
menu,soche,thanhtoan - ❌
menumonanngon,khusochenguyenlieu
- ✅
-
Mỗi Package Một Trách Nhiệm:
- Package
menu: Chỉ về món ăn - Package
thanhtoan: Chỉ về tính tiền - Không trộn lẫn trách nhiệm!
- Package
-
Hàm Public vs Private:
- Public (chữ HOA): Những gì người khác cần dùng
- Private (chữ thường): Chi tiết nội bộ, không cần chia sẻ
-
Cấu Trúc Thư Mục Rõ Ràng:
myrestaurant/
├── cmd/ # Cac chuong trinh chinh
├── pkg/ # Cac package tai su dung
├── internal/ # Code rieng, khong chia se
└── api/ # API endpoints -
Import Gọn Gàng:
import (
// Standard library truoc
"fmt"
"time"
// External packages sau
"github.com/gin-gonic/gin"
// Local packages cuoi cung
"myrestaurant/menu"
"myrestaurant/soche"
) -
Đặt Tên Module Đúng Chuẩn:
- Nếu code trên GitHub:
github.com/username/myrestaurant - Nếu code local:
myrestauranthoặcexample.com/myrestaurant
- Nếu code trên GitHub:
🎓 Bạn Đã Học Được
- ✅ Package = khu vực trong bếp, mỗi khu có chức năng riêng
- ✅
package main= bếp chính, nơi bắt đầu chương trình - ✅ Import = mượn dụng cụ/công thức từ package khác
- ✅ Hàm chữ HOA = public (ai cũng dùng được)
- ✅ Hàm chữ thường = private (chỉ trong package đó)
- ✅
go.mod= danh sách nguyên liệu cần thiết cho nhà hàng - ✅ Tổ chức code tốt = bếp gọn gàng, dễ tìm kiếm, dễ bảo trì
🍜 Món Tiếp Theo
Bếp đã sắp xếp gọn gàng! Giờ cần học cách kiểm tra độ chín của món ăn:
👉 Kiểm Tra Độ Chín - Control Structures
💡 Lời Khuyên Cuối: Bếp sắp xếp gọn gàng = code dễ đọc, dễ sửa, dễ mở rộng. Đầu tư thời gian sắp xếp bếp ngay từ đầu sẽ giúp bạn tiết kiệm rất nhiều thời gian sau này!