วัสดุทางเทคนิค

โปรแกรม 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() มาตามนั้น ที่ดีก่อนเอ่าสั้งทดสอบจะตรวงเยยงวัตถิสึน