☕ 5-Min Tech Story #09

ปรัชญา Go: ทำไมถึงบังคับให้พิมพ์ "if err != nil" ซ้ำซากแทนที่จะใช้ try-catch สบายๆ?

⏱️ ใช้เวลาอ่านประมาณ: 4 นาที 15 วินาที

มีมแซวโปรแกรมเมอร์ Go ที่ฮิตที่สุดในโลก คือรูปคีย์บอร์ดที่มีแค่ 3 ปุ่ม: ปุ่มตัว i, ตัว f และปุ่มลัดพิมพ์ประโยค if err != nil

คนที่ย้ายมาจากสาย Java, Python หรือ C# มักจะบ่นอุบว่า "ภาษาเกิดใหม่แท้ๆ ทำไมชีวิตดูลำบากจังวะ? ทำไมไม่เอา try-catch มาครอบทีเดียวสิบฟังก์ชันแล้วจบๆ ไป?"

แต่รู้ไหมครับว่า... ทีมผู้สร้าง Go (ระดับบิดาแห่งวงการอย่าง Ken Thompson และ Rob Pike) ตั้งใจตัด Exception ทิ้งอย่างเลือดเย็น เพราะเหตุผลที่ซ่อนอยู่เบื้องหลัง

🚪 ท่อวาปที่มองไม่เห็น: มนต์ดำของ try-catch

ในภาษาที่มีระบบ Exception เวลาคุณเขียนโค้ด:

try {
  val user = getUser(id)
  val bill = calculateBill(user)
  chargeCard(bill)
} catch (e: Exception) {
  log.error("พังวะ", e)
}

ดูเผินๆ เหมือนอ่านง่ายเป็นระเบียบ... แต่ในความเป็นจริง มันคือ "Goto ที่ซ่อนตัวอยู่" (Invisible Control Flow)

ถ้าฟังก์ชัน calculateBill() พังกลางคัน โค้ดจะหยุดทำงานทันทีแล้ว "วาปข้ามมิติ" ลงไปที่บล็อก catch ข้างล่างเลย! คุณไม่มีทางรู้เลยว่า ระหว่างทางมันเปิดไฟล์ค้างไว้ไหม? ปิด Database Connection หรือยัง? หรือทิ้ง State อะไรเละเทะไว้ครึ่งๆ กลางๆ ในหน่วยความจำ

📦 Error ก็แค่ของชิ้นหนึ่ง (Errors Are Values)

Go เชื่อในหลักการสุดโต่งข้อหนึ่งคือ:

"การที่เกิดข้อผิดพลาด (เช่น ต่อเน็ตไม่ติด, หาไฟล์ไม่เจอ) ไม่ใช่เรื่องวิเศษเหนือธรรมชาติ (Exceptional) แต่มันคือผลลัพธ์ปกติของชีวิตที่ต้องเตรียมรับมือเสมอ"

Go จึงบังคับให้ฟังก์ชันคืนค่า (ผลลัพธ์, error) ออกมาคู่กันเป็น Tuple เสมอ:

data, err := readFile("config.json")
if err != nil {
  // จัดการตรงนี้เลย ไม่มีการแอบซ่อน ไม่มีท่อวาป!
  return nil, fmt.Errorf("โหลดคอนฟิกพัง: %w", err)
}

เมื่อโค้ดไม่มีการวาปกระโดดข้ามมิติ:

💡 5-Min Takeaway

"ความสะดวกตอนพิมพ์ ไม่ได้แปลว่าอ่านง่ายตอนบำรุงรักษา" Go ยอมให้นิ้วคุณเมื่อยขึ้นนิดหน่อยด้วยการพิมพ์ if err != nil แลกกับการทำให้ระบบไม่มี Hidden Flow ที่พร้อมจะระเบิดเป็นลูกโซ่ ทำให้ไม่ว่าใครเข้ามาอ่านโค้ดทีหลัง ก็ไล่สายตาตามสเต็ปการทำงานจริงของโปรแกรมได้อย่างตรงไปตรงมาเสมอ