panic() vs os.Exit() ในภาษา Golang

Teerapong Singthong 👨🏻‍💻
iamgoangle
Published in
1 min readNov 9, 2018
Victor Rodvan — Unsplash

สำหรับคนที่เขียน 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 ไม่ได้เลย จำเป็นต้องปิดการทำงานของโปรแกรมทันที

อย่างไรก็ดี ไม่ควรเกิดเหตุการณ์ ทั้งสองเลยจะดีมาก…

--

--

Teerapong Singthong 👨🏻‍💻
iamgoangle

Engineering Manager, ex-Solution Engineering Lead at LINE | Tech | Team Building | System Design | Architecture | SWE | Large Scaling System