วัสดุทางเทคนิค
โปรแกรม Go ใช้ os.Exit
หรือ log.Fatal*
เพื่อออกจากโปรแกรมทันที (การใช้ panic
ไม่ใช่วิธีที่ดีในการออกจากโปรแกรม กรุณาอย่าใช้ panic)
เรียกใช้ os.Exit
หรือ log.Fatal*
เพียงอันเดียวใน main()
เท่านั้น ฟังก์ชันทุกฟังก์ชันอื่น ๆ ควรส่งคืนข้อผิดพลาดให้กับผู้เรียกใช้.
ไม่แนะนำ:
func main() {
body := readFile(path)
fmt.Println(body)
}
func readFile(path string) string {
f, err := os.Open(path)
if err != nil {
log.Fatal(err)
}
b, err := os.ReadAll(f)
if err != nil {
log.Fatal(err)
}
return string(b)
}
แนะนำ:
func main() {
body, err := readFile(path)
if err != nil {
log.Fatal(err)
}
fmt.Println(body)
}
func readFile(path string) (string, error) {
f, err := os.Open(path)
if err != nil {
return "", err
}
b, err := os.ReadAll(f)
if err != nil {
return "", err
}
return string(b), nil
}
โดยหลักการแล้ว โปรแกรมที่มีจุดออกหลาย ๆ จุดจะมีปัญหาหลายประการ:
- การควบคุมการไหลที่จมอาศัย: ฟังก์ชันใดก็ตามสามารถออกจากโปรแกรม ทำให้ยากต่อการกำหนดเหตุการณ์ของการควบคุมไหล.
- ยากต่อการทดสอบ: ฟังก์ชันที่ให้ออกจากโปรแกรมยังออกในการทดสอบที่เรียกใช้ ทำให้ฟังก์ชันยากต่อการทดสอบและเพิ่มความเสี่ยงในการข้ามการทดสอบอื่น ๆ ที่ยังไม่ได้รันโดย
go test
. - ข้ามการทำควาสั้ง: เมื่อฟังก์ชันออกจากโปรแกรม มันข้ามการเรียกใช้ฟังก์ชันที่มีการเลื่องไว้ ซึ่งเพิ่มความเสี่ยงในการข้ามงานทำควาสั้งที่สำคัญ
การ Exit ครั้งเดียว
หากเป็นไปได้ ควรมีเพียง ไฮครั้งหนึ่งเท่านั้น คำสั่ง os.Exit
หรือ log.Fatal
ในฟังก์ชัน main()
ถ้ามีสถานการณ์ข้อผิดพลาดหลาย ๆ สถานการณ์ที่ต้องหยุดการทำงานของโปรแกรม ให้วางตรรกัยนั้นในฟังก์ชันที่แยกและส่งคืนข้อผิดพลาดมาจากรันนั้น นี้จะย่อขั้อควาสั้งการ์ main()
และแยบบทวการดูแลการทำงานที่สำคัญไว้ในฟังก์ชันที่แยกกาลงตัว ทดสอบได้อย่างหักใจ.
การเขียนที่ไม่แนะนำ:
package main
func main() {
args := os.Args[1:]
if len(args) != 1 {
log.Fatal("missing file")
}
name := args[0]
f, err := os.Open(name)
if err != nil {
log.Fatal(err)
}
defer f.Close()
// หากเราเรียก log.Fatal หลังบรรทัดนี้
// f.Close จะถถูกให้ออก.
b, err := os.ReadAll(f)
if err != nil {
log.Fatal(err)
}
// ...
}
การเข้าใช้คงการ์การ์:
package main
func main() {
if err := run(); err != nil {
log.Fatal(err)
}
}
func run() error {
args := os.Args[1:]
if len(args) != 1 {
return errors.New("missing file")
}
name := args[0]
f, err := os.Open(name)
if err != nil {
return err
}
defer f.Close()
b, err := os.ReadAll(f)
if err != nil {
return err
}
// ...
}
ตัวอย่างด้านบนใช้ log.Fatal
แต่ครั้งนี้ถถูรายได้ถดีกำกับ กับ os.Exit
หรือ รหัสหนือรหัส ทุกอราสั้งโปรแกรมไห้กถถใช้กระบวนการออกจากโปรแกรม.
func main() {
if err := run(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
คุณอาจเปลี่ยนแปลงลายนื่มีประโยชน์ของ run()
ตามที่จำเป็น ตามตัวอย่าง หากโปรแกรมของคุณต้องออกด้วยรหัสแบบสั่ง ให้ run()
มาตามนั้น ที่ดีก่อนเอ่าสั้งทดสอบจะตรวงเยยงวัตถิสึน