Back to notes
mastery-backend-go
Featured

Standard Go Project Layout: วางโครงสร้างโปรเจกต์ Go แบบมืออาชีพ

ทำไมต้องมี cmd? internal คืออะไร? เจาะลึกโครงสร้างโปรเจกต์ Go ที่เป็นมาตรฐานสากล เพื่อให้โค้ดของคุณพรีเมียมและ Scale ได้อย่างไร้ขีดจำกัด

January 30, 20262 min read readNNexis by Seereen

🛑 1. The Problem First: "ถุงเดียวใส่ทุุกอย่าง" (The Monolithic Folder)

ลองดูโปรเจกต์ Go ที่เขียนเสร็จไวแต่ขยายต่อไม่ได้:

HLJS GO
// ❌ Naive Approach: ทุกอย่างกองรวมกันอยู่ที่ root ของโปรเจกต์
my-app/
  main.go
  user.go
  db.go
  auth.go
  utils.go
// 🌋 พัง! เมื่อโปรเจกต์มี 50 ไฟล์ คุณจะหาไม่เจอว่าอะไรคือ Logic หลัก อะไรคือ Utility
// และที่ร้ายที่สุดคือ "Circular Dependency" (ไฟล์ A import B, B import A)
// ซึ่งเป็นข้อห้ามรุนแรงของ Go ที่จะทำให้คุณ Compile โค้ดไม่ผ่านทันที

ปัญหา: Go เข้มงวดเรื่องความสัมพันธ์ระหว่าง Package มาก การวางโครงสร้างผิดตั้งแต่วันแรกจะกลายเป็นกำแพงเหล็กที่กั้นไม่ให้คุณขยายระบบได้ในอนาคต นี่คือสาเหตุที่เราต้องการ "ระบบระเบียบ" ที่ได้รับการยอมรับทั่วโลกครับ


💡 2. Real-Life Analogy: การจัดแผนผังในห้างสรรพสินค้า

  • cmd/ (ประตูหน้าห้าง): เหมือน "ทางเข้าและจุดประชาสัมพันธ์". มีหน้าที่แค่บอกว่าจะเปิดแอร์ตอนไหน เปิดไฟตอนไหน (Wiring System) แต่ไม่มีสินค้าขายที่นี่
  • internal/ (คลังสินค้าส่วนตัว): เหมือน "ห้องพนักงานและคลังหลังบ้าน". คนนอก (โปรเจกต์อื่น) ห้ามเข้ามายุ่ง เป็นที่เก็บความลับและสูตรอาหารทั้งหมดของร้าน
  • pkg/ (สินค้าบรรจุห่อ): เหมือน "สินค้าที่วางขายบนชั้น". ใครจะหยิบไปใช้ก็ได้ เป็น Utility ที่ออกแบบมาให้เป็นมิตรกับคนภายนอก
  • api/ (ป้ายเมนู): เหมือน "แผ่นพับโฆษณา". บอกโลกว่าเรามีอะไรขายบ้าง (Swagger/Proto) โดยไม่ต้องเข้ามาดูในครัว

🚀 3. Execution Journey: มหากาพย์การแยกชั้น (Layering)

หัวใจของโปรเจกต์ Go ที่ดีคือการแบ่งแยกหน้าที่ให้ชัดเจน

🛠 Step-by-step:

  1. The Entry (cmd/): สร้าง main.go เพื่อทำหน้าที่เชื่อมต่อ Config, Database และเริ่มรันแอป เท่านั้น!
  2. The Encapsulation (internal/): เก็บ Business Logic ทั้งหมดไว้ที่นี่ เพื่อให้ Go-Compiler ป้องกันไม่ให้คนอื่นแอบใช้โค้ดเรา
  3. The 3-Layer Rule:
    • Handler: รับ Request (HTTP/gRPC) แล้วส่งต่อ (ไม่ต้องคิด Logic)
    • Service: สมองของระบบ (คำนวณ, ตัดสินใจ)
    • Repository: มือและเท้า (คุยกับ DB)
HLJS GO
// ✅ Best Practice: โครงสร้างโฟลเดอร์ที่สะอาดตา
my-project/
  ├── cmd/
  │   └── server/main.go    // 🛠 จุดรวมพล (The Wirer)
  ├── internal/
  │   ├── user/
  │   │   ├── handler.go   // 🛠 ด่านหน้า
  │   │   ├── service.go   // 🛠 สมอง
  │   │   └── repository.go // 🛠 ฐานข้อมูล
  └── go.mod

🪤 4. The Junior Trap: โรค "Logic พอกอยู่ที่ main.go"

จูเนียร์มักจะเขียนทุุกอย่างลงในไฟล์เดียวเพราะมันสะดวกดี:

HLJS GO
// ❌ Junior Trap: main.go ที่ยาว 1,000 บรรทัด
func main() {
    db, _ := sql.Open(...)
    // 🌋 พัง! เขียน Router, Auth, และ Database Query รวมกันใน main function
    http.HandleFunc("/user", func(w, r) {
        // Query ตรงนี้เลย...
    })
}

ระวัง: main.go ควรเป็นที่สำหรับ "ประกอบร่าง" (Compose) เท่านั้น ไม่ใช่ที่สำหรับ "สร้างลอจิก" ✅ การแก้ไข: เขียน Logic แยกเป็น Package แล้วให้ main.go เป็นคนเรียกใช้ (Inject) เข้ามาทำงานแทนครับ


⚖️ 5. The Why Matrix: Standard Layout vs Flat Layout

หัวข้อFlat Layout (ไฟล์กองรวม)Standard Layout (มืออาชีพ)
ความเร็วในการเริ่ม⚡⚡⚡ เร็วมาก (โปรเจกต์เล็ก)ช้ากว่า (ต้องสร้างหลายโฟลเดอร์)
การดูแลระยะยาว🐢 ยากนรก (Circular Import ง่าย)⚡⚡⚡ ง่าย (แยกส่วนชัดเจน)
การทำงานเป็นทีมสับสน เดินทับรอยกันบ่อย⚡⚡⚡ ทำงานทับซ้อนกันได้สบาย
ความ Securityต่ำ (ทุกตัวเป็น Public)🚀 สูง (ใช้ internal ป้องกันคนนอก)

🎓 6. Senior Mindset Summary

การเป็น Senior คือการมองว่า "เราไม่ได้จัดโฟลเดอร์เพื่อความสวยงาม แต่เพื่อลด Cognitive Load ของทีม". เมื่อทุุกอย่างอยู่ในที่ที่ควรอยู่ นักพัฒนาคนใหม่ที่เข้าทีมมาจะสามารถเริ่มงานได้ทันทีโดยไม่ต้องถามหาคู่มือ นี่คือสุดยอดของการออกแบบวิศวกรรมครับ!

Share this note

© 2026 My Notes by Seereen