การสร้าง API จริงครั้งแรกของผมด้วย Go และ Gin
ผมกำลังเปลี่ยนจากการเรียนรู้ทฤษฎีไปสู่การลงมือปฏิบัติจริง
หลังจากศึกษาเรื่อง structs, interfaces, goroutines และการจัดการ error ผมก็ได้สร้าง Orders API ที่ใช้งานได้จริงโดยใช้ Go และ Gin framework
API นี้ทำงาน 3 อย่าง:
- สร้างคำสั่งซื้อ
- ดึงข้อมูลคำสั่งซื้อตาม ID
- แสดงรายการคำสั่งซื้อทั้งหมด
ผมเลือกใช้ Gin เพราะมันช่วยให้การทำ routing และ middleware ง่ายขึ้น โดยมี helper functions อย่าง c.JSON และ c.AbortWithStatusJSON ซึ่งเครื่องมือเหล่านี้ช่วยลดการเขียนโค้ดที่ซ้ำซ้อน
โครงสร้างโปรเจกต์: ผมใช้การจัดวางแพ็กเกจแบบ flat เพื่อให้โค้ดดูสะอาดตา:
- handler: จัดการ HTTP logic
- model: กำหนดโครงสร้างข้อมูล (data shapes)
- store: จัดการการจัดเก็บข้อมูล
- middleware: จัดการเรื่อง logging และ requests
ทางเลือกทางเทคนิคที่สำคัญ:
• การตรวจสอบความถูกต้องของข้อมูล (Data Validation) ผมใช้ struct tags สำหรับการทำ JSON serialization และยังใช้ Gin binding tags ด้วย เพื่อให้มั่นใจว่าฟิลด์ที่จำเป็นต้องมีอยู่ครบถ้วน และจำนวน (amounts) ต้องมากกว่าศูนย์
• การจัดเก็บข้อมูลและการทำงานแบบขนาน (Persistence and Concurrency)
เวอร์ชันปัจจุบันใช้การจัดเก็บข้อมูลในหน่วยความจำ (in-memory store) โดยผมใช้ sync.RWMutex เพื่อจัดการการเข้าถึงข้อมูลแบบพร้อมกัน (concurrent access) ซึ่งช่วยให้สามารถอ่านข้อมูลได้หลายรายการพร้อมกัน แต่ยังคงความปลอดภัยในการเขียนข้อมูล
• อินเทอร์เฟซ (Interfaces)
ตัว handler จะขึ้นอยู่กับ OrderStore interface โดยไม่สนใจว่าข้อมูลจะถูกเก็บไว้ในหน่วยความจำหรือในฐานข้อมูล ซึ่งช่วยให้การเปลี่ยนเลเยอร์การจัดเก็บข้อมูล (storage layer) ทำได้ง่าย
• การจัดการข้อผิดพลาด (Error Handling)
ผมใช้ errors.Is เพื่อตรวจสอบข้อผิดพลาดเฉพาะเจาะจง เช่น ErrNotFound ซึ่งช่วยให้ API สามารถส่ง HTTP status code 404 ที่ถูกต้องกลับไปยังผู้ใช้ได้
• มิดเดิลแวร์ (Middleware) ผมได้สร้าง custom logger ขึ้นมาเอง เพื่อติดตาม method, path, status code และระยะเวลาในการประมวลผลคำขอ (request duration)
การตั้งค่านี้เป็นการรวบรวมทุกอย่างที่ได้เรียนรู้มาจากส่วนก่อนหน้าเข้าด้วยกัน มันเป็นรากฐานที่ใช้งานได้จริง มีโครงสร้างที่ดี และสามารถขยายระบบได้ (scalable)
แล้วคุณล่ะ มีวิธีการจัดโครงสร้างโปรเจกต์ Go อย่างไร? คุณชอบแบบ flat packages หรือแบบที่มีการซ้อนกันลึกๆ ตามโดเมน (domain-driven nesting)?
แหล่งที่มา: https://dev.to/mihirmohapatra/building-my-first-real-api-in-go-with-gin-3kio