ควรใช้ os.Exit () และ panic () เมื่อใด


96

มีใครช่วยอธิบายความแตกต่างที่สำคัญระหว่างos.Exit()และpanic()และวิธีการใช้งานใน Go ได้ไหม


11
เป็นเพียงความคิดเห็นที่หวังว่าจะช่วยในการอ่านรหัส Go ในอนาคต: ในโค้ดตัวอย่างจำนวนมากpanicถูกใช้เพื่อออกจากข้อผิดพลาดเนื่องจากเข้าใจง่ายและกำจัดการนำเข้าแพ็คเกจอื่น ๆ นี่ไม่ได้หมายความว่ามันดีหรือเป็นสำนวน! . เป็นเพียงอุปกรณ์ประหยัดพื้นที่สำหรับโค้ดตัวอย่าง สำรอง IRL panicสำหรับมากสถานการณ์พิเศษ
Intermernet

2
อืม.. ดี) โดยเฉพาะตัวย่อ "IRL" - มันใหม่สำหรับฉัน :) คุณช่วยอธิบายได้ไหมว่า panic ช่วยลดการนำเข้าแพ็คเกจได้อย่างไร
Timur Fayzrakhmanov

5
panicเป็น builtin ก็ขอแนะนำ (ขึ้นอยู่กับสถานการณ์) เพื่อใช้สิ่งที่ชอบos.Exit, log.Fatalเป็นต้นซึ่งจะกลับรหัสข้อผิดพลาดระบบปฏิบัติการ (แนะนำเสมอถ้าเป็นไปได้) ทั้งหมดนี้เกี่ยวข้องกับการนำเข้าแพ็กเกจดังนั้นโค้ดตัวอย่างจึง "รกรุงรัง" ควรใช้โค้ดตัวอย่างเพื่อสาธิตวิธีแก้ปัญหาเฉพาะเท่านั้น อาจมีปัญหาอื่น ๆ เกี่ยวกับโค้ดซึ่งทำให้โค้ดมีความซับซ้อนมากขึ้นหากแสดงให้เห็นอย่างถูกต้องดังนั้นจึงเบี่ยงเบนไปจากคำอธิบายของคำตอบที่ได้รับ YMMV.
Intermernet

1
ตกลงเข้าใจแล้ว!) ขอบคุณมาก) ฉันเห็นว่ายังมีตัวย่ออื่นสำหรับคำศัพท์ของฉัน :)
Timur Fayzrakhmanov

2
NP ยินดีให้ความช่วยเหลือและเพิ่มคำศัพท์ย่อของคุณ :-)
Intermernet

คำตอบ:


85

ก่อนอื่นเมื่อใดก็ตามที่คุณมีคำถาม "วิธีใช้ในทางปฏิบัติ" วิธีที่ดีในการเริ่มต้นคือค้นหาซอร์สโค้ด Go (หรือฐานรหัส Go ที่ใหญ่พอจริงๆ) และเอกสารแพคเกจเพื่อหาคำตอบ

ตอนนี้os.Exitและpanicค่อนข้างแตกต่างกัน panicใช้เมื่อโปรแกรมหรือส่วนของโปรแกรมถึงสถานะที่ไม่สามารถกู้คืนได้

เมื่อpanicถูกเรียกรวมทั้งโดยปริยายสำหรับข้อผิดพลาดรันไทม์เช่นการจัดทำดัชนีสไลซ์นอกขอบเขตหรือการยืนยันประเภทล้มเหลวมันจะหยุดการทำงานของฟังก์ชันปัจจุบันทันทีและเริ่มคลายสแต็กของ goroutine โดยเรียกใช้ฟังก์ชันรอการตัดบัญชีไปพร้อมกัน หากการคลี่คลายไปถึงด้านบนสุดของสแต็กของ goroutine โปรแกรมจะตาย

os.Exitใช้เมื่อคุณต้องการยกเลิกโปรแกรมทันทีโดยไม่มีความเป็นไปได้ในการกู้คืนหรือเรียกใช้คำสั่งล้างข้อมูลที่รอการตัดบัญชีและส่งคืนรหัสข้อผิดพลาด (ที่โปรแกรมอื่นสามารถใช้เพื่อรายงานสิ่งที่เกิดขึ้น) สิ่งนี้มีประโยชน์ในการทดสอบเมื่อคุณรู้แล้วว่าหลังจากการทดสอบครั้งนี้ล้มเหลวการทดสอบอื่น ๆ ก็จะล้มเหลวเช่นกันดังนั้นคุณอาจออกตอนนี้ก็ได้เช่นกัน นอกจากนี้ยังสามารถใช้เมื่อโปรแกรมของคุณทำทุกอย่างที่จำเป็นต้องทำและตอนนี้จำเป็นต้องออกเช่นหลังจากพิมพ์ข้อความช่วยเหลือ

เวลาส่วนใหญ่คุณจะไม่ใช้panic(คุณควรส่งคืนerrorแทน) และคุณแทบไม่จำเป็นต้องใช้os.Exitนอกบางกรณีในการทดสอบและการยุติโปรแกรมอย่างรวดเร็ว


9
"สิ่งนี้มีประโยชน์ในการทดสอบเมื่อคุณรู้แล้วว่าหลังจากการทดสอบครั้งนี้ล้มเหลวการทดสอบอื่น ๆ ก็จะล้มเหลวเช่นกัน ... " กลิ่นของการทดสอบต่อต้านการทดสอบตาม ในชุดทดสอบข้อเขียนแต่ละแบบทดสอบแยกกัน ผลของการทดสอบใด ๆ ไม่ควรระบุผลของการทดสอบอื่นใด
gotgenes

1
@gotgenes ไม่จำเป็น หากฉันมีการทดสอบว่าฟังก์ชันบางฟังก์ชันส่งคืนโครงสร้างที่ไม่ใช่ศูนย์และการทดสอบนั้นล้มเหลวฉันสามารถคาดหวังได้ว่าการทดสอบทั้งหมดที่ตรวจสอบค่าของโครงสร้างจะล้มเหลวเช่นกัน เป็นรหัสที่ขึ้นอยู่กับไม่ใช่การทดสอบ (ที่กล่าวว่าฉันจะไม่ใช้exitในกรณีนั้นฉันแค่คาดหวังว่าจะมีการยืนยันที่ล้มเหลวจำนวนมาก)
David Moles

84

ก่อนอื่นos.Exit()สามารถใช้เพื่อออกจากโปรแกรมได้ตามปกติโดยไม่มีข้อผิดพลาดและไม่ต้องตกใจนั่นคือความแตกต่างที่สำคัญอย่างหนึ่ง recoverก็คือการที่ความหวาดกลัวที่ไหนสักแห่งที่สามารถจับได้และถูกละเลยหรือเข้าสู่ระบบโดยใช้

แต่ถ้าเรากำลังพูดถึงรหัสทางออกที่ผิดพลาดสมมติว่า:

ใช้panicเมื่อมีสิ่งผิดปกติอย่างน่ากลัวซึ่งอาจเป็นข้อผิดพลาดของโปรแกรมเมอร์ที่ควรถูกตรวจพบก่อนที่จะไปผลิต นี่คือสาเหตุที่พิมพ์สแตก

ใช้os.Exit(errorCode)หรืออะไรทำนองนั้นหากคุณต้องการ:

  1. ควบคุมรหัสทางออกของโปรแกรมเพื่อวัตถุประสงค์ในการเขียนสคริปต์

  2. ต้องการทางออกอย่างเป็นระเบียบเมื่อเกิดข้อผิดพลาดที่คาดไว้ (เช่นข้อผิดพลาดในการป้อนข้อมูลของผู้ใช้)

ดังนั้นโดยพื้นฐานแล้วความตื่นตระหนกสำหรับคุณรหัสทางออกที่ไม่ดีมีไว้สำหรับผู้ใช้ของคุณ


ขอบคุณมากที่มีประโยชน์!)
Timur Fayzrakhmanov

14
"โดยพื้นฐานแล้วความตื่นตระหนกมีไว้สำหรับคุณรหัสทางออกที่ไม่ดีมีไว้สำหรับผู้ใช้ของคุณ" <- เคล็ดลับสุดเจ๋ง
psousa

1
เราบอกได้ไหมว่า panic () เกี่ยวข้องกับการเรียก assert () ตามปกติในภาษา C ธรรมดาหรือไม่? ดี .. ฉันรู้ว่าฉันมักจะลบการเรียกที่ยืนยันก่อนที่จะผลักดันไปสู่การผลิตฉันเปิดใช้งานเมื่อทดสอบคุณลักษณะใหม่เท่านั้น สิ่งที่ฉันพูดคือส่วนใหญ่ฉันใช้ assert () เพื่อตรวจสอบค่าคงที่ที่ฉันเดาว่าต้องเป็นจริงในรหัสของฉัน คุณเห็นการใช้งานแบบเดียวกันสำหรับ panic () หรือไม่? :-)
yves Baumes

7

ความแตกต่างที่สำคัญคือ:

  1. os.Exit ข้ามการดำเนินการของฟังก์ชันรอการตัดบัญชี
  2. ด้วย os.Exitคุณสามารถระบุรหัสทางออก
  3. panicกำลังยุติในขณะที่os.Exitไม่อยู่ (ดูเหมือนคำตอบอื่นไม่ได้กล่าวถึงเรื่องนี้)

หากคุณต้องการเรียกใช้ฟังก์ชันรอการตัดบัญชีคุณไม่มีทางเลือกpanicอื่นนอกจาก (ในทางกลับกันหากคุณต้องการข้ามการเรียกใช้ฟังก์ชันรอการตัดบัญชีให้ใช้os.Exit)

หากกำหนดฟังก์ชันที่ไม่ใช่โมฆะในลักษณะดังกล่าว:

  1. ฟังก์ชันนี้ประกอบด้วยสาขาจำนวนมาก
  2. ทุกสาขาถูกยกเลิกด้วยreturnหรือpanic

จากนั้นคุณจะไม่สามารถแทนที่panicด้วยos.Exitมิฉะนั้นคอมไพเลอร์จะปฏิเสธที่จะคอมไพล์โปรแกรมโดยกล่าวว่า "การคืนค่าที่ขาดหายไปเมื่อสิ้นสุดฟังก์ชัน" (Go เป็นใบ้มากที่นี่แม้log.Panicจะไม่ยุติฟังก์ชันก็ตาม)

ภายใต้เงื่อนไขอื่น ๆ :

  1. ใช้ panicเมื่อมีบางอย่างเกิดขึ้นจริงเช่นการเขียนโปรแกรมตรรกะผิดพลาด
  2. ใช้os.Exitเมื่อคุณต้องการออกทันทีพร้อมระบุรหัสทางออก
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.