panic() vs os.Exit() ในภาษา Golang
สำหรับคนที่เขียน Go มาสักพักจะพบว่าหลายบทความแนะนำว่า อย่าพยายามให้แอพที่เราออกแบบนั้นเกิด panic() เด็ดขาดถ้าไม่จำเป็น แต่สำหรับมือใหม่นั้น ยังไม่แน่ใจว่ามันคืออะไรกันแน่ ดังนั้น ในวันนี้เรามาทำความเข้าใจเรื่อง panic() และ os.Exit() กันครับ
panic()
ใช้กับสถานการณ์ที่เราต้องการให้เกิด run time error
เช่น index out of bound in slice
หรือ wrong type assetion
รวมไปถึงสถานการณ์ที่ error นั้นๆ เราคิดว่าไม่สามารถ recover ได้
ตัวอย่าง
- ต่อ Redis ไม่ได้
- ต่อ Database ไม่ได้
- อ่าน config ที่ใช้ init program ไม่ได้
จาก usecase ข้างบนเป็นตัวอย่างถ้าเกิด error จุดนี้ แล้วถ้าพิจารณาแล้วว่า โปรแกรมทำงานต่อไม่ได้เลยถ้าขาดมัน ก็เข้าข่ายเงื่อนไข
เมื่อเกิด panic() event ถัดไป คือ การสร้าง panicking และ deferred
func Poison() {
panic("Inject poison to you!")
}go func() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in my go routine", r)
}
}()
Poison()
}
GO บอกว่าถ้าเราไม่ต้องให้ panic ที่เกิดขึ้นนั้น กระทบกับ Go Routine หลัก เมื่อเกิด panicking state ให้เราทำ recover()
ไว้ด้วยที่ defer
ให้นึกถึงการทำงานแบบ stack หรือ top of stack execution ที่ตัวในสุด คือ ผู้ถูกเรียก จะต้องไม่สร้างความเสียหายให้กับ ผู้เรียก ใช้งาน
แต่ท้ายที่สุดคงไม่มีใครอยากให้เกิด panic state จริงไหมครับ ถ้าเราทำ lib ควรทำ แค่ error state ก็พอ เพื่อให้โปรแกรมทำต่อ และ handler error ได้เอง
os.Exit(error code)
ต้องการให้โปรแกรมปัจจุบันปิดการทำงานทันที พร้อมบอก statusCode
และไม่มีการทำ defer ด้วย
ใช้ตอนไหน?
เมื่อเรารู้แน่ๆ ทำไงก็ defer หรือ recover ไม่ได้เลย จำเป็นต้องปิดการทำงานของโปรแกรมทันที
อย่างไรก็ดี ไม่ควรเกิดเหตุการณ์ ทั้งสองเลยจะดีมาก…